From f30e4272885d8c75fcace3c140d6a866fff56ebe Mon Sep 17 00:00:00 2001 From: speakeasybot Date: Sat, 26 Apr 2025 00:24:55 +0000 Subject: [PATCH] ci: regenerated with OpenAPI Doc , Speakeasy CLI 1.540.0 --- .gitignore | 3 +- .speakeasy/gen.lock | 122 +- .speakeasy/workflow.lock | 29 + .speakeasy/workflow.yaml | 3 + README.md | 13 +- RELEASES.md | 12 +- docs/data-sources/file.md | 102 -- docs/index.md | 2 +- docs/resources/file.md | 150 --- .../epilot-file_file/data-source.tf | 5 - examples/provider/provider.tf | 2 +- examples/resources/epilot-file_file/import.sh | 1 - .../resources/epilot-file_file/resource.tf | 41 - gen.yaml | 12 +- go.mod | 48 +- go.sum | 114 +- .../float32planmodifier/suppress_diff.go | 56 + .../int32planmodifier/suppress_diff.go | 56 + internal/planmodifiers/utils/state_check.go | 3 +- internal/provider/file_data_source.go | 311 ----- internal/provider/file_data_source_sdk.go | 136 -- internal/provider/file_resource.go | 815 ------------ internal/provider/file_resource_sdk.go | 255 ---- internal/provider/provider.go | 44 +- internal/provider/reflect/helpers.go | 2 +- internal/provider/typeconvert/date.go | 23 + internal/provider/typeconvert/datetime.go | 23 + internal/provider/typeconvert/int32.go | 14 + internal/provider/types/base_entity_acl.go | 11 - internal/provider/types/base_entity_owner.go | 10 - internal/provider/types/file_item.go | 13 - internal/provider/types/s3_ref.go | 10 - internal/provider/utils.go | 250 +++- internal/sdk/.gitignore | 2 + internal/sdk/deprecated.go | 254 ++-- internal/sdk/file.go | 1106 +++++------------ internal/sdk/internal/hooks/hooks.go | 1 + internal/sdk/internal/utils/env.go | 16 + internal/sdk/internal/utils/form.go | 6 +- internal/sdk/internal/utils/json.go | 8 +- internal/sdk/internal/utils/queryparams.go | 29 +- internal/sdk/internal/utils/requestbody.go | 10 +- internal/sdk/internal/utils/retries.go | 152 ++- internal/sdk/internal/utils/utils.go | 23 + .../sdk/models/operations/accesspubliclink.go | 12 +- internal/sdk/models/operations/getfile.go | 12 +- internal/sdk/models/operations/options.go | 23 +- internal/sdk/models/shared/fileentity.go | 40 +- .../models/shared/savecustomfilepayload.go | 2 +- .../shared/savefilefromsourceurlpayload.go | 2 +- internal/sdk/models/shared/savefilepayload.go | 6 +- .../sdk/models/shared/savefilepayloadv2.go | 165 +-- .../sdk/models/shared/saves3filepayload.go | 2 +- internal/sdk/preview.go | 489 ++------ internal/sdk/publiclinks.go | 488 +++----- internal/sdk/retry/config.go | 132 ++ internal/sdk/sdk.go | 6 +- internal/sdk/session.go | 244 +--- .../validators/float32validators/not_null.go | 49 + .../validators/int32validators/not_null.go | 49 + 60 files changed, 1932 insertions(+), 4087 deletions(-) create mode 100644 .speakeasy/workflow.lock delete mode 100644 docs/data-sources/file.md delete mode 100644 docs/resources/file.md delete mode 100644 examples/data-sources/epilot-file_file/data-source.tf delete mode 100644 examples/resources/epilot-file_file/import.sh delete mode 100644 examples/resources/epilot-file_file/resource.tf create mode 100644 internal/planmodifiers/float32planmodifier/suppress_diff.go create mode 100644 internal/planmodifiers/int32planmodifier/suppress_diff.go delete mode 100644 internal/provider/file_data_source.go delete mode 100644 internal/provider/file_data_source_sdk.go delete mode 100644 internal/provider/file_resource.go delete mode 100644 internal/provider/file_resource_sdk.go create mode 100644 internal/provider/typeconvert/date.go create mode 100644 internal/provider/typeconvert/datetime.go create mode 100644 internal/provider/typeconvert/int32.go delete mode 100644 internal/provider/types/base_entity_acl.go delete mode 100644 internal/provider/types/base_entity_owner.go delete mode 100644 internal/provider/types/file_item.go delete mode 100644 internal/provider/types/s3_ref.go create mode 100644 internal/sdk/internal/utils/env.go create mode 100644 internal/validators/float32validators/not_null.go create mode 100644 internal/validators/int32validators/not_null.go diff --git a/.gitignore b/.gitignore index 3cfe1e1..1afdea8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.speakeasy/temp/ # .gitignore .terraform .terraform* @@ -30,8 +31,6 @@ override.tf.json .terraformrc terraform.rc .DS_Store - terraform-provider-epilot-file - original.yaml original_modified.yaml diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 0767fa0..7185792 100755 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: 11c8545a-deb6-44f9-ba56-e71722af6a51 management: - docChecksum: 0383a3b8b71da53f168ab4cd3da53caa + docChecksum: dcd5a495c6952d2b8060f3be050d3f83 docVersion: 0.2.0 - speakeasyVersion: 1.422.1 - generationVersion: 2.438.15 - releaseVersion: 0.5.0 - configChecksum: 166ca9b280afae98c5bf4536bf99033d + speakeasyVersion: 1.540.0 + generationVersion: 2.593.3 + releaseVersion: 0.6.0 + configChecksum: c90f584d1ac4a524bb0fd2420612c330 repoURL: https://github.com/epilot-dev/terraform-provider-epilot-file.git repoSubDirectory: . published: true @@ -14,28 +14,26 @@ features: terraform: additionalDependencies: 0.1.0 additionalProperties: 0.1.2 - constsAndDefaults: 0.1.4 - core: 3.25.0 - deprecations: 2.81.1 + constsAndDefaults: 0.2.1 + core: 3.41.6 + deprecations: 2.82.0 envVarSecurityUsage: 0.1.0 - globalSecurity: 2.81.9 + globalSecurity: 2.81.10 globalServerURLs: 2.82.1 inputOutputModels: 2.83.0 nullables: 0.0.0 - retries: 2.81.1 - unions: 2.81.16 + unions: 2.81.17 generatedFiles: - .gitattributes - USAGE.md - examples/README.md - - examples/data-sources/epilot-file_file/data-source.tf - examples/provider/provider.tf - - examples/resources/epilot-file_file/import.sh - - examples/resources/epilot-file_file/resource.tf - go.mod - go.sum - internal/planmodifiers/boolplanmodifier/suppress_diff.go + - internal/planmodifiers/float32planmodifier/suppress_diff.go - internal/planmodifiers/float64planmodifier/suppress_diff.go + - internal/planmodifiers/int32planmodifier/suppress_diff.go - internal/planmodifiers/int64planmodifier/suppress_diff.go - internal/planmodifiers/listplanmodifier/suppress_diff.go - internal/planmodifiers/mapplanmodifier/suppress_diff.go @@ -44,10 +42,6 @@ generatedFiles: - internal/planmodifiers/setplanmodifier/suppress_diff.go - internal/planmodifiers/stringplanmodifier/suppress_diff.go - internal/planmodifiers/utils/state_check.go - - internal/provider/file_data_source.go - - internal/provider/file_data_source_sdk.go - - internal/provider/file_resource.go - - internal/provider/file_resource_sdk.go - internal/provider/provider.go - internal/provider/reflect/diags.go - internal/provider/reflect/doc.go @@ -63,18 +57,16 @@ generatedFiles: - internal/provider/reflect/primitive.go - internal/provider/reflect/slice.go - internal/provider/reflect/struct.go - - internal/provider/types/base_entity_acl.go - - internal/provider/types/base_entity_owner.go - - internal/provider/types/file_item.go - - internal/provider/types/s3_ref.go + - internal/provider/typeconvert/date.go + - internal/provider/typeconvert/datetime.go + - internal/provider/typeconvert/int32.go - internal/provider/utils.go - internal/sdk/.gitattributes - - internal/sdk/.gitignore - - internal/sdk/CONTRIBUTING.md - internal/sdk/deprecated.go - internal/sdk/file.go - internal/sdk/internal/hooks/hooks.go - internal/sdk/internal/utils/contenttype.go + - internal/sdk/internal/utils/env.go - internal/sdk/internal/utils/form.go - internal/sdk/internal/utils/headers.go - internal/sdk/internal/utils/json.go @@ -140,7 +132,9 @@ generatedFiles: - internal/validators/JSONParseValidator.go - internal/validators/RFC3339Validator.go - internal/validators/boolvalidators/not_null.go + - internal/validators/float32validators/not_null.go - internal/validators/float64validators/not_null.go + - internal/validators/int32validators/not_null.go - internal/validators/int64validators/not_null.go - internal/validators/listvalidators/not_null.go - internal/validators/mapvalidators/not_null.go @@ -157,11 +151,12 @@ examples: parameters: query: activity_id: "01F130Q52Q6MWSNS8N2AVXV4JN" + async: false requestBody: - application/json: {"_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["tag1", "tag2"], "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "relations": [], "source_url": "https://some-api-url.com/download?file_id=123", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}} + application/json: {"_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["tag1", "tag2"], "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "relations": [{"_schema": "contact", "entity_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8"}, {"_schema": "contact", "entity_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8"}], "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}} responses: "201": - application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["tag1", "tag2"], "_title": "document.pdf", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "versions": []} + application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [{"org_id": "123", "user_id": "123"}], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_schema": "file", "_tags": ["tag1", "tag2"], "_title": "document.pdf", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "type": "video", "versions": [{"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}, {"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}]} uploadFile: speakeasy-default-upload-file: parameters: @@ -179,31 +174,35 @@ examples: id: "ef7d985c-2385-44f4-9c71-ae06a52264f8" query: activity_id: "01F130Q52Q6MWSNS8N2AVXV4JN" + strict: false responses: "200": - application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["tag1", "tag2"], "_title": "document.pdf", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "versions": []} + application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [{"org_id": "123", "user_id": "123"}, {"org_id": "123", "user_id": "123"}, {"org_id": "123", "user_id": "123"}], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_schema": "file", "_tags": ["tag1", "tag2"], "_title": "document.pdf", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "type": "document_template", "versions": [{"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}, {"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}, {"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}]} downloadFile: speakeasy-default-download-file: parameters: path: id: "ef7d985c-2385-44f4-9c71-ae06a52264f8" - query: {} + query: + version: 0 + attachment: true responses: "200": application/json: {"download_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/temp/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf?AWSParams=123"} downloadFiles: speakeasy-default-download-files: requestBody: - application/json: [] + application/json: [{"id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "version": 0}] responses: "200": - application/json: [] + application/json: [{"download_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/temp/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf?AWSParams=123"}] downloadS3File: speakeasy-default-download-s3-file: parameters: query: s3_key: "" s3_bucket: "" + attachment: true responses: "200": application/json: {"download_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/temp/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf?AWSParams=123"} @@ -212,57 +211,72 @@ examples: parameters: path: id: "ef7d985c-2385-44f4-9c71-ae06a52264f8" - query: {} + query: + source_url: false + strict: false + async: false responses: "200": - application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["tag1", "tag2"], "_title": "document.pdf", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "versions": []} + application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [{"org_id": "123", "user_id": "123"}, {"org_id": "123", "user_id": "123"}, {"org_id": "123", "user_id": "123"}], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_schema": "file", "_tags": ["tag1", "tag2"], "_title": "document.pdf", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "type": "application", "versions": []} saveFileV2: New file from s3ref: parameters: query: activity_id: "01F130Q52Q6MWSNS8N2AVXV4JN" + fill_activity: false + strict: false + async: false requestBody: - application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["string"], "_title": "document.pdf", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "type": "document"} + application/json: {"_tags": ["string"], "access_control": "private", "filename": "document.pdf", "type": "document", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}} responses: "200": - application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["tag1", "tag2"], "_title": "document.pdf", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "versions": []} + application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [{"org_id": "123", "user_id": "123"}], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_schema": "file", "_tags": ["tag1", "tag2"], "_title": "document.pdf", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "type": "document_template", "versions": [{"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}]} Update existing file with relations: parameters: query: activity_id: "01F130Q52Q6MWSNS8N2AVXV4JN" + fill_activity: false + strict: false + async: false requestBody: - application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["tag1", "tag2"], "_title": "document.pdf", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf"} + application/json: {"_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "relations": [{"_schema": "contact", "entity_id": "77a1e0cc-7b92-4d41-8cce-eefd317ec004"}], "shared_with_end_customer": true} responses: "200": - application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["tag1", "tag2"], "_title": "document.pdf", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "versions": []} + application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [{"org_id": "123", "user_id": "123"}, {"org_id": "123", "user_id": "123"}], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_schema": "file", "_tags": ["tag1", "tag2"], "_title": "document.pdf", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "type": "unknown", "versions": [{"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}, {"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}, {"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}]} New file from source_url: parameters: query: activity_id: "01F130Q52Q6MWSNS8N2AVXV4JN" + fill_activity: false + strict: false + async: false requestBody: - application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["string"], "_title": "document.pdf", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "source_url": "https://docs.epilot.io/document.pdf", "type": "document"} + application/json: {"_tags": ["string"], "access_control": "private", "filename": "document.pdf", "type": "document", "source_url": "https://docs.epilot.io/document.pdf"} responses: "200": - application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["tag1", "tag2"], "_title": "document.pdf", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "versions": []} + application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [{"org_id": "123", "user_id": "123"}], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_schema": "file", "_tags": ["tag1", "tag2"], "_title": "document.pdf", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "type": "image", "versions": [{"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}]} File with custom download URL (external): parameters: query: activity_id: "01F130Q52Q6MWSNS8N2AVXV4JN" + fill_activity: false + strict: false + async: false requestBody: - application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["string"], "_title": "document.pdf", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "type": "document"} + application/json: {"_tags": ["string"], "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "type": "document", "shared_with_end_customer": true} responses: "200": - application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_tags": ["tag1", "tag2"], "_title": "document.pdf", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "versions": []} + application/json: {"_acl": {"delete": ["org:456"], "edit": ["org:456"], "view": ["org:456"]}, "_id": "ef7d985c-2385-44f4-9c71-ae06a52264f8", "_manifest": ["123e4567-e89b-12d3-a456-426614174000"], "_org": "123", "_owners": [{"org_id": "123", "user_id": "123"}, {"org_id": "123", "user_id": "123"}, {"org_id": "123", "user_id": "123"}], "_purpose": ["8d396871-95a0-4c9d-bb4d-9eda9c35776c", "da7cdf9a-01be-40c9-a29c-9a8f9f0de6f8"], "_schema": "file", "_tags": ["tag1", "tag2"], "_title": "document.pdf", "access_control": "private", "custom_download_url": "https://some-api-url.com/download?file_id=123", "filename": "document.pdf", "mime_type": "application/pdf", "public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234, "source_url": "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf", "type": "presentation", "versions": [{"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}, {"filename": "document.pdf", "mime_type": "image/jpeg", "readable_size": "1.2 MB", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "size_bytes": 1234}]} uploadFilePublic: Upload an image file: requestBody: - application/json: {"filename": "image.png", "index_tag": "2f6a377c8e78", "metadata": {"color": "blue"}, "mime_type": "image/png"} + application/json: {"filename": "image.png", "mime_type": "image/png"} responses: "201": application/json: {"s3ref": {"bucket": "epilot-prod-user-content", "key": "123/temp/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "upload_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/temp/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf?AWSParams=123"} Upload a document: requestBody: - application/json: {"filename": "document.pdf", "index_tag": "2f6a377c8e78", "metadata": {"color": "blue"}, "mime_type": "application/pdf"} + application/json: {"filename": "document.pdf", "mime_type": "application/pdf"} responses: "201": application/json: {"s3ref": {"bucket": "epilot-prod-user-content", "key": "123/temp/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "upload_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/temp/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf?AWSParams=123"} @@ -272,7 +286,7 @@ examples: query: file_entity_id: "ef7d985c-2385-44f4-9c71-ae06a52264f8" requestBody: - application/json: {"filename": "image.png", "index_tag": "2f6a377c8e78", "metadata": {"color": "blue"}, "mime_type": "image/png"} + application/json: {"filename": "image.png", "mime_type": "image/png"} responses: "201": application/json: {"public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/temp/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "upload_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/temp/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf?AWSParams=123"} @@ -281,7 +295,7 @@ examples: query: file_entity_id: "ef7d985c-2385-44f4-9c71-ae06a52264f8" requestBody: - application/json: {"filename": "document.pdf", "index_tag": "2f6a377c8e78", "metadata": {"color": "blue"}, "mime_type": "application/pdf"} + application/json: {"filename": "document.pdf", "mime_type": "application/pdf"} responses: "201": application/json: {"public_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf", "s3ref": {"bucket": "epilot-prod-user-content", "key": "123/temp/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf"}, "upload_url": "https://epilot-prod-user-content.s3.eu-central-1.amazonaws.com/123/temp/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf?AWSParams=123"} @@ -289,12 +303,16 @@ examples: speakeasy-default-verify-custom-download-url: requestBody: application/json: {"custom_download_url": "https://some-api-url.com?file_id=123&expires_at=1699273500029&signature=abcdefg"} + responses: + "200": + application/json: {} accessPublicLink: speakeasy-default-access-public-link: parameters: path: id: "13d22918-36bd-4227-9ad4-2cb978788c8d" filename: "invoice-2023-12.pdf" + query: {} generatePublicLink: speakeasy-default-generate-public-link: parameters: @@ -310,7 +328,7 @@ examples: id: "13d22918-36bd-4227-9ad4-2cb978788c8d" responses: "200": - application/json: {"results": []} + application/json: {"results": [{"id": "3ef5c6d9-818d-45e6-8efb-b1de59079a1c", "link": "https://file.sls.epilot.io/v1/files/public/links/3ef5c6d9-818d-45e6-8efb-b1de59079a1c"}]} revokePublicLink: speakeasy-default-revoke-public-link: parameters: @@ -324,13 +342,15 @@ examples: parameters: path: id: "ef7d985c-2385-44f4-9c71-ae06a52264f8" - query: {} + query: + version: 0 previewPublicFile: speakeasy-default-preview-public-file: parameters: path: id: "ef7d985c-2385-44f4-9c71-ae06a52264f8" - query: {} + query: + version: 0 previewS3File: speakeasy-default-preview-s3-file: requestBody: @@ -341,7 +361,7 @@ examples: query: key: "" bucket: "" - deleteSession: - speakeasy-default-delete-session: {} - getSession: - speakeasy-default-get-session: {} + deleteSession: {} + getSession: {} +examplesVersion: 1.0.1 +generatedTests: {} diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock new file mode 100644 index 0000000..5693028 --- /dev/null +++ b/.speakeasy/workflow.lock @@ -0,0 +1,29 @@ +speakeasyVersion: 1.540.0 +sources: + my-source: + sourceNamespace: my-source + sourceRevisionDigest: sha256:aec2327d994c8902843e8c3f7c6876ebf8d7848354ec70907c1013303fd825e5 + sourceBlobDigest: sha256:959b44cb41730f235554e3ddff1940be1567cd18c1b0a282c3ddeec6a193815c + tags: + - latest + - speakeasy-sdk-regen-1730852495 + - 0.2.0 +targets: + terraform: + source: my-source + sourceNamespace: my-source + sourceRevisionDigest: sha256:aec2327d994c8902843e8c3f7c6876ebf8d7848354ec70907c1013303fd825e5 + sourceBlobDigest: sha256:959b44cb41730f235554e3ddff1940be1567cd18c1b0a282c3ddeec6a193815c +workflow: + workflowVersion: 1.0.0 + speakeasyVersion: latest + sources: + my-source: + inputs: + - location: https://docs.api.epilot.io/file.yaml + registry: + location: registry.speakeasyapi.dev/epilot/epilot/my-source + targets: + terraform: + target: terraform + source: my-source diff --git a/.speakeasy/workflow.yaml b/.speakeasy/workflow.yaml index 6ebb44c..cb056d0 100644 --- a/.speakeasy/workflow.yaml +++ b/.speakeasy/workflow.yaml @@ -1,8 +1,11 @@ workflowVersion: 1.0.0 +speakeasyVersion: latest sources: my-source: inputs: - location: https://docs.api.epilot.io/file.yaml + registry: + location: registry.speakeasyapi.dev/epilot/epilot/my-source targets: terraform: target: terraform diff --git a/README.md b/README.md index d767863..754e64f 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ terraform { required_providers { epilot-file = { source = "epilot-dev/epilot-file" - version = "0.5.0" + version = "0.6.0" } } } @@ -117,10 +117,7 @@ provider_installation { ### Resources -* [epilot-file_file](docs/resources/file.md) ### Data Sources - -* [epilot-file_file](docs/data-sources/file.md) @@ -131,10 +128,12 @@ File API: Upload and manage epilot Files ## Table of Contents + +* [epilot-file](#epilot-file) + * [Installation](#installation) + * [Testing the provider locally](#testing-the-provider-locally) + * [Available Resources and Data Sources](#available-resources-and-data-sources) -* [Installation](#installation) -* [Available Resources and Data Sources](#available-resources-and-data-sources) -* [Testing the provider locally](#testing-the-provider-locally) diff --git a/RELEASES.md b/RELEASES.md index 0a3b4a6..a92bddf 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -14,4 +14,14 @@ Based on: - OpenAPI Doc 0.1.0 - Speakeasy CLI 1.148.0 (2.237.3) https://github.com/speakeasy-api/speakeasy ### Generated -- [terraform v0.1.0] . \ No newline at end of file +- [terraform v0.1.0] . + +## 2025-04-26 00:23:36 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.540.0 (2.593.3) https://github.com/speakeasy-api/speakeasy +### Generated +- [terraform v0.6.0] . +### Releases +- [Terraform v0.6.0] https://registry.terraform.io/providers/epilot-dev/epilot-file/0.6.0 - . \ No newline at end of file diff --git a/docs/data-sources/file.md b/docs/data-sources/file.md deleted file mode 100644 index 3276844..0000000 --- a/docs/data-sources/file.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "epilot-file_file Data Source - terraform-provider-epilot-file" -subcategory: "" -description: |- - File DataSource ---- - -# epilot-file_file (Data Source) - -File DataSource - -## Example Usage - -```terraform -data "epilot-file_file" "my_file" { - async = true - id = "ef7d985c-2385-44f4-9c71-ae06a52264f8" - strict = false -} -``` - - -## Schema - -### Optional - -- `async` (Boolean) Don't wait for updated entity to become available in Search API. Useful for large migrations -- `strict` (Boolean) When passed true, the response will contain only fields that match the schema, with non-matching fields included in `__additional` - -### Read-Only - -- `access_control` (String) -- `acl` (Attributes) Access control list (ACL) for an entity. Defines sharing access to external orgs or users. (see [below for nested schema](#nestedatt--acl)) -- `additional` (Map of String) Additional fields that are not part of the schema -- `created_at` (String) -- `custom_download_url` (String) Custom external download url used for the file -- `filename` (String) -- `id` (String) The ID of this resource. -- `manifest` (List of String) Manifest ID used to create/update the entity -- `mime_type` (String) MIME type of the file -- `org` (String) -- `owners` (Attributes List) (see [below for nested schema](#nestedatt--owners)) -- `public_url` (String) Direct URL for file (public only if file access control is public-read) -- `purpose` (List of String) -- `readable_size` (String) Human readable file size -- `s3ref` (Attributes) (see [below for nested schema](#nestedatt--s3ref)) -- `schema` (String) -- `size_bytes` (Number) File size in bytes -- `source_url` (String) Source URL for the file. Included if the entity was created from source_url, or when ?source_url=true -- `tags` (List of String) -- `title` (String) -- `type` (String) -- `updated_at` (String) -- `versions` (Attributes List) (see [below for nested schema](#nestedatt--versions)) - - -### Nested Schema for `acl` - -Read-Only: - -- `delete` (List of String) -- `edit` (List of String) -- `view` (List of String) - - - -### Nested Schema for `owners` - -Read-Only: - -- `org_id` (String) -- `user_id` (String) - - - -### Nested Schema for `s3ref` - -Read-Only: - -- `bucket` (String) -- `key` (String) - - - -### Nested Schema for `versions` - -Read-Only: - -- `filename` (String) -- `mime_type` (String) -- `readable_size` (String) -- `s3ref` (Attributes) (see [below for nested schema](#nestedatt--versions--s3ref)) -- `size_bytes` (Number) - - -### Nested Schema for `versions.s3ref` - -Read-Only: - -- `bucket` (String) -- `key` (String) diff --git a/docs/index.md b/docs/index.md index 3130b5a..ebaa031 100644 --- a/docs/index.md +++ b/docs/index.md @@ -17,7 +17,7 @@ terraform { required_providers { epilot-file = { source = "epilot-dev/epilot-file" - version = "0.5.0" + version = "0.6.0" } } } diff --git a/docs/resources/file.md b/docs/resources/file.md deleted file mode 100644 index d7e0207..0000000 --- a/docs/resources/file.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "epilot-file_file Resource - terraform-provider-epilot-file" -subcategory: "" -description: |- - File Resource ---- - -# epilot-file_file (Resource) - -File Resource - -## Example Usage - -```terraform -resource "epilot-file_file" "my_file" { - access_control = "public-read" - acl = { - delete = [ - "org:456" - ] - edit = [ - "org:456" - ] - view = [ - "org:456" - ] - } - activity_id = "01F130Q52Q6MWSNS8N2AVXV4JN" - additional = { - "see" : jsonencode("documentation"), - } - async = true - custom_download_url = "https://some-api-url.com/download?file_id=123" - filename = "document.pdf" - fill_activity = true - id = "ef7d985c-2385-44f4-9c71-ae06a52264f8" - manifest = [ - "123e4567-e89b-12d3-a456-426614174000" - ] - mime_type = "application/pdf" - purpose = [ - "..." - ] - s3ref = { - bucket = "epilot-prod-user-content" - key = "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf" - } - source_url = "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf" - strict = false - tags = [ - "..." - ] - title = "document.pdf" - type = "font" -} -``` - - -## Schema - -### Optional - -- `access_control` (String) Default: "private"; must be one of ["private", "public-read"] -- `acl` (Attributes) Access control list (ACL) for an entity. Defines sharing access to external orgs or users. (see [below for nested schema](#nestedatt--acl)) -- `activity_id` (String) Activity to include in event feed -- `additional` (Map of String) Additional fields that are not part of the schema -- `async` (Boolean) Don't wait for updated entity to become available in Search API. Useful for large migrations. Default: false -- `custom_download_url` (String) Custom external download url used for the file -- `filename` (String) -- `fill_activity` (Boolean) Update the diff and entity for the custom activity included in the query. -Pending state on activity is automatically ended when activity is filled. -Default: false -- `manifest` (List of String) Manifest ID used to create/update the entity -- `mime_type` (String) MIME type of the file -- `purpose` (List of String) -- `s3ref` (Attributes) (see [below for nested schema](#nestedatt--s3ref)) -- `source_url` (String) Source URL for the file. Included if the entity was created from source_url, or when ?source_url=true -- `strict` (Boolean) When passed true, the response will contain only fields that match the schema, with non-matching fields included in `__additional`. Default: false -- `tags` (List of String) -- `title` (String) -- `type` (String) must be one of ["document", "document_template", "text", "image", "video", "audio", "spreadsheet", "presentation", "font", "archive", "application", "unknown"] - -### Read-Only - -- `created_at` (String) -- `id` (String) The ID of this resource. -- `org` (String) -- `owners` (Attributes List) (see [below for nested schema](#nestedatt--owners)) -- `public_url` (String) Direct URL for file (public only if file access control is public-read) -- `readable_size` (String) Human readable file size -- `schema` (String) must be "file" -- `size_bytes` (Number) File size in bytes -- `updated_at` (String) -- `versions` (Attributes List) (see [below for nested schema](#nestedatt--versions)) - - -### Nested Schema for `acl` - -Optional: - -- `delete` (List of String) -- `edit` (List of String) -- `view` (List of String) - - - -### Nested Schema for `s3ref` - -Optional: - -- `bucket` (String) Not Null -- `key` (String) Not Null - - - -### Nested Schema for `owners` - -Read-Only: - -- `org_id` (String) -- `user_id` (String) - - - -### Nested Schema for `versions` - -Read-Only: - -- `filename` (String) -- `mime_type` (String) -- `readable_size` (String) -- `s3ref` (Attributes) (see [below for nested schema](#nestedatt--versions--s3ref)) -- `size_bytes` (Number) - - -### Nested Schema for `versions.s3ref` - -Read-Only: - -- `bucket` (String) -- `key` (String) - -## Import - -Import is supported using the following syntax: - -```shell -terraform import epilot-file_file.my_epilot-file_file "ef7d985c-2385-44f4-9c71-ae06a52264f8" -``` diff --git a/examples/data-sources/epilot-file_file/data-source.tf b/examples/data-sources/epilot-file_file/data-source.tf deleted file mode 100644 index 0090c78..0000000 --- a/examples/data-sources/epilot-file_file/data-source.tf +++ /dev/null @@ -1,5 +0,0 @@ -data "epilot-file_file" "my_file" { - async = true - id = "ef7d985c-2385-44f4-9c71-ae06a52264f8" - strict = false -} \ No newline at end of file diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index 6670b8a..c386459 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -2,7 +2,7 @@ terraform { required_providers { epilot-file = { source = "epilot-dev/epilot-file" - version = "0.5.0" + version = "0.6.0" } } } diff --git a/examples/resources/epilot-file_file/import.sh b/examples/resources/epilot-file_file/import.sh deleted file mode 100644 index 031c010..0000000 --- a/examples/resources/epilot-file_file/import.sh +++ /dev/null @@ -1 +0,0 @@ -terraform import epilot-file_file.my_epilot-file_file "ef7d985c-2385-44f4-9c71-ae06a52264f8" diff --git a/examples/resources/epilot-file_file/resource.tf b/examples/resources/epilot-file_file/resource.tf deleted file mode 100644 index c486b9f..0000000 --- a/examples/resources/epilot-file_file/resource.tf +++ /dev/null @@ -1,41 +0,0 @@ -resource "epilot-file_file" "my_file" { - access_control = "public-read" - acl = { - delete = [ - "org:456" - ] - edit = [ - "org:456" - ] - view = [ - "org:456" - ] - } - activity_id = "01F130Q52Q6MWSNS8N2AVXV4JN" - additional = { - "see" : jsonencode("documentation"), - } - async = true - custom_download_url = "https://some-api-url.com/download?file_id=123" - filename = "document.pdf" - fill_activity = true - id = "ef7d985c-2385-44f4-9c71-ae06a52264f8" - manifest = [ - "123e4567-e89b-12d3-a456-426614174000" - ] - mime_type = "application/pdf" - purpose = [ - "..." - ] - s3ref = { - bucket = "epilot-prod-user-content" - key = "123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf" - } - source_url = "https://productengineer-content.s3.eu-west-1.amazonaws.com/product-engineer-checklist.pdf" - strict = false - tags = [ - "..." - ] - title = "document.pdf" - type = "font" -} \ No newline at end of file diff --git a/gen.yaml b/gen.yaml index de8daec..7fb46e0 100644 --- a/gen.yaml +++ b/gen.yaml @@ -4,11 +4,13 @@ generation: usageSnippets: optionalPropertyRendering: withExample fixes: - nameResolutionDec2023: false + nameResolutionFeb2025: false parameterOrderingFeb2024: false requestResponseComponentNamesFeb2024: false + securityFeb2025: false auth: oAuth2ClientCredentialsEnabled: false + oAuth2PasswordEnabled: false telemetryEnabled: false go: version: 0.0.1 @@ -27,12 +29,18 @@ go: outputModelSuffix: output packageName: openapi terraform: - version: 0.5.0 + version: 0.6.0 additionalDataSources: [] additionalDependencies: {} + additionalEphemeralResources: [] + additionalProviderAttributes: + httpHeaders: "" + tlsSkipVerify: "" additionalResources: [] allowUnknownFieldsInWeakUnions: false author: epilot-dev + defaultErrorName: SDKError + enableTypeDeduplication: true environmentVariables: [] imports: option: openapi diff --git a/go.mod b/go.mod index 07a48d6..8322b92 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,15 @@ module github.com/epilot-dev/terraform-provider-epilot-file -go 1.22.0 +go 1.23.0 require ( - github.com/cenkalti/backoff/v4 v4.2.0 github.com/ericlagergren/decimal v0.0.0-20221120152707-495c53812d05 - github.com/hashicorp/terraform-plugin-docs v0.19.4 - github.com/hashicorp/terraform-plugin-framework v1.12.0 - github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 - github.com/hashicorp/terraform-plugin-go v0.24.0 + github.com/hashicorp/go-uuid v1.0.3 + github.com/hashicorp/terraform-plugin-docs v0.20.1 + github.com/hashicorp/terraform-plugin-framework v1.14.1 + github.com/hashicorp/terraform-plugin-framework-validators v0.17.0 + github.com/hashicorp/terraform-plugin-go v0.26.0 + github.com/hashicorp/terraform-plugin-log v0.9.0 ) require ( @@ -21,7 +22,7 @@ require ( github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect - github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect + github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/fatih/color v1.16.0 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -30,16 +31,15 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.6.1 // indirect - github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/hashicorp/go-plugin v1.6.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-version v1.7.0 // indirect - github.com/hashicorp/hc-install v0.7.0 // indirect + github.com/hashicorp/hc-install v0.9.0 // indirect github.com/hashicorp/terraform-exec v0.21.0 // indirect - github.com/hashicorp/terraform-json v0.22.1 // indirect - github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect - github.com/hashicorp/terraform-registry-address v0.2.3 // indirect + github.com/hashicorp/terraform-json v0.23.0 // indirect + github.com/hashicorp/terraform-registry-address v0.2.4 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/huandu/xstrings v1.3.3 // indirect @@ -56,19 +56,19 @@ require ( github.com/spf13/cast v1.5.0 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/yuin/goldmark v1.7.1 // indirect + github.com/yuin/goldmark v1.7.7 // indirect github.com/yuin/goldmark-meta v1.1.0 // indirect - github.com/zclconf/go-cty v1.14.4 // indirect + github.com/zclconf/go-cty v1.15.0 // indirect go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.32.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/grpc v1.66.2 // indirect - google.golang.org/protobuf v1.34.2 // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect + google.golang.org/grpc v1.69.4 // indirect + google.golang.org/protobuf v1.36.3 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index f9e8505..7ff3b5a 100644 --- a/go.sum +++ b/go.sum @@ -20,12 +20,10 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= -github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q= +github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= -github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= -github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= @@ -48,6 +46,10 @@ github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+ github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -67,36 +69,38 @@ github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuD github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= -github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= +github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog= +github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hc-install v0.7.0 h1:Uu9edVqjKQxxuD28mR5TikkKDd/p55S8vzPC1659aBk= -github.com/hashicorp/hc-install v0.7.0/go.mod h1:ELmmzZlGnEcqoUMKUuykHaPCIR1sYLYX+KSggWSKZuA= +github.com/hashicorp/hc-install v0.9.0 h1:2dIk8LcvANwtv3QZLckxcjyF5w8KVtiMxu6G6eLhghE= +github.com/hashicorp/hc-install v0.9.0/go.mod h1:+6vOP+mf3tuGgMApVYtmsnDoKWMDcFXeTxCACYZ8SFg= github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ= github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg= -github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec= -github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A= -github.com/hashicorp/terraform-plugin-docs v0.19.4 h1:G3Bgo7J22OMtegIgn8Cd/CaSeyEljqjH3G39w28JK4c= -github.com/hashicorp/terraform-plugin-docs v0.19.4/go.mod h1:4pLASsatTmRynVzsjEhbXZ6s7xBlUw/2Kt0zfrq8HxA= -github.com/hashicorp/terraform-plugin-framework v1.12.0 h1:7HKaueHPaikX5/7cbC1r9d1m12iYHY+FlNZEGxQ42CQ= -github.com/hashicorp/terraform-plugin-framework v1.12.0/go.mod h1:N/IOQ2uYjW60Jp39Cp3mw7I/OpC/GfZ0385R0YibmkE= -github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 h1:bxZfGo9DIUoLLtHMElsu+zwqI4IsMZQBRRy4iLzZJ8E= -github.com/hashicorp/terraform-plugin-framework-validators v0.13.0/go.mod h1:wGeI02gEhj9nPANU62F2jCaHjXulejm/X+af4PdZaNo= -github.com/hashicorp/terraform-plugin-go v0.24.0 h1:2WpHhginCdVhFIrWHxDEg6RBn3YaWzR2o6qUeIEat2U= -github.com/hashicorp/terraform-plugin-go v0.24.0/go.mod h1:tUQ53lAsOyYSckFGEefGC5C8BAaO0ENqzFd3bQeuYQg= +github.com/hashicorp/terraform-json v0.23.0 h1:sniCkExU4iKtTADReHzACkk8fnpQXrdD2xoR+lppBkI= +github.com/hashicorp/terraform-json v0.23.0/go.mod h1:MHdXbBAbSg0GvzuWazEGKAn/cyNfIB7mN6y7KJN6y2c= +github.com/hashicorp/terraform-plugin-docs v0.20.1 h1:Fq7E/HrU8kuZu3hNliZGwloFWSYfWEOWnylFhYQIoys= +github.com/hashicorp/terraform-plugin-docs v0.20.1/go.mod h1:Yz6HoK7/EgzSrHPB9J/lWFzwl9/xep2OPnc5jaJDV90= +github.com/hashicorp/terraform-plugin-framework v1.14.1 h1:jaT1yvU/kEKEsxnbrn4ZHlgcxyIfjvZ41BLdlLk52fY= +github.com/hashicorp/terraform-plugin-framework v1.14.1/go.mod h1:xNUKmvTs6ldbwTuId5euAtg37dTxuyj3LHS3uj7BHQ4= +github.com/hashicorp/terraform-plugin-framework-validators v0.17.0 h1:0uYQcqqgW3BMyyve07WJgpKorXST3zkpzvrOnf3mpbg= +github.com/hashicorp/terraform-plugin-framework-validators v0.17.0/go.mod h1:VwdfgE/5Zxm43flraNa0VjcvKQOGVrcO4X8peIri0T0= +github.com/hashicorp/terraform-plugin-go v0.26.0 h1:cuIzCv4qwigug3OS7iKhpGAbZTiypAfFQmw8aE65O2M= +github.com/hashicorp/terraform-plugin-go v0.26.0/go.mod h1:+CXjuLDiFgqR+GcrM5a2E2Kal5t5q2jb0E3D57tTdNY= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= -github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= -github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM= +github.com/hashicorp/terraform-registry-address v0.2.4 h1:JXu/zHB2Ymg/TGVCRu10XqNa4Sh2bWcqCNyKWjnCPJA= +github.com/hashicorp/terraform-registry-address v0.2.4/go.mod h1:tUNYTVyCtU4OIGXXMDp7WNcJ+0W1B4nmstVDgHMjfAU= github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= @@ -143,8 +147,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -160,8 +164,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= @@ -169,34 +173,44 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= -github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark v1.7.7 h1:5m9rrB1sW3JUMToKFQfb+FGt1U7r57IHu5GrYrG2nqU= +github.com/yuin/goldmark v1.7.7/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0= -github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= -github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= +github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw= go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= +go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -210,8 +224,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -219,20 +233,20 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= diff --git a/internal/planmodifiers/float32planmodifier/suppress_diff.go b/internal/planmodifiers/float32planmodifier/suppress_diff.go new file mode 100644 index 0000000..e4ca952 --- /dev/null +++ b/internal/planmodifiers/float32planmodifier/suppress_diff.go @@ -0,0 +1,56 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package float32planmodifier + +import ( + "context" + "github.com/epilot-dev/terraform-provider-epilot-file/internal/planmodifiers/utils" + + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" +) + +const ( + // ExplicitSuppress strategy suppresses "(known after changes)" messages unless we're in the initial creation + ExplicitSuppress = iota +) + +// SuppressDiff returns a plan modifier that propagates a state value into the planned value, when it is Known, and the Plan Value is Unknown +func SuppressDiff(strategy int) planmodifier.Float32 { + return suppressDiff{ + strategy: strategy, + } +} + +// suppressDiff implements the plan modifier. +type suppressDiff struct { + strategy int +} + +// Description returns a human-readable description of the plan modifier. +func (m suppressDiff) Description(_ context.Context) string { + return "Once set, the value of this attribute in state will not change." +} + +// MarkdownDescription returns a markdown description of the plan modifier. +func (m suppressDiff) MarkdownDescription(_ context.Context) string { + return "Once set, the value of this attribute in state will not change." +} + +// PlanModifyFloat32 implements the plan modification logic. +func (m suppressDiff) PlanModifyFloat32(ctx context.Context, req planmodifier.Float32Request, resp *planmodifier.Float32Response) { + // Do nothing if there is a known planned value. + if !req.PlanValue.IsUnknown() { + return + } + + // Do nothing if there is an unknown configuration value + if req.ConfigValue.IsUnknown() { + return + } + + if utils.IsAllStateUnknown(ctx, req.State) { + return + } + + resp.PlanValue = req.StateValue +} diff --git a/internal/planmodifiers/int32planmodifier/suppress_diff.go b/internal/planmodifiers/int32planmodifier/suppress_diff.go new file mode 100644 index 0000000..7625ded --- /dev/null +++ b/internal/planmodifiers/int32planmodifier/suppress_diff.go @@ -0,0 +1,56 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package int32planmodifier + +import ( + "context" + "github.com/epilot-dev/terraform-provider-epilot-file/internal/planmodifiers/utils" + + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" +) + +const ( + // ExplicitSuppress strategy suppresses "(known after changes)" messages unless we're in the initial creation + ExplicitSuppress = iota +) + +// SuppressDiff returns a plan modifier that propagates a state value into the planned value, when it is Known, and the Plan Value is Unknown +func SuppressDiff(strategy int) planmodifier.Int32 { + return suppressDiff{ + strategy: strategy, + } +} + +// suppressDiff implements the plan modifier. +type suppressDiff struct { + strategy int +} + +// Description returns a human-readable description of the plan modifier. +func (m suppressDiff) Description(_ context.Context) string { + return "Once set, the value of this attribute in state will not change." +} + +// MarkdownDescription returns a markdown description of the plan modifier. +func (m suppressDiff) MarkdownDescription(_ context.Context) string { + return "Once set, the value of this attribute in state will not change." +} + +// PlanModifyInt32 implements the plan modification logic. +func (m suppressDiff) PlanModifyInt32(ctx context.Context, req planmodifier.Int32Request, resp *planmodifier.Int32Response) { + // Do nothing if there is a known planned value. + if !req.PlanValue.IsUnknown() { + return + } + + // Do nothing if there is an unknown configuration value + if req.ConfigValue.IsUnknown() { + return + } + + if utils.IsAllStateUnknown(ctx, req.State) { + return + } + + resp.PlanValue = req.StateValue +} diff --git a/internal/planmodifiers/utils/state_check.go b/internal/planmodifiers/utils/state_check.go index 51d5362..0ea64fb 100644 --- a/internal/planmodifiers/utils/state_check.go +++ b/internal/planmodifiers/utils/state_check.go @@ -4,6 +4,7 @@ package utils import ( "context" + "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/tfsdk" @@ -12,7 +13,7 @@ import ( func IsAllStateUnknown(ctx context.Context, state tfsdk.State) bool { attrs := state.Schema.GetAttributes() anyFound := false - for k, _ := range attrs { + for k := range attrs { attrValue := new(attr.Value) state.GetAttribute(ctx, path.Root(k), attrValue) if attrValue != nil && !(*attrValue).IsUnknown() && !(*attrValue).IsNull() { diff --git a/internal/provider/file_data_source.go b/internal/provider/file_data_source.go deleted file mode 100644 index 91c4bfc..0000000 --- a/internal/provider/file_data_source.go +++ /dev/null @@ -1,311 +0,0 @@ -// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. - -package provider - -import ( - "context" - "fmt" - tfTypes "github.com/epilot-dev/terraform-provider-epilot-file/internal/provider/types" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/operations" - "github.com/hashicorp/terraform-plugin-framework/datasource" - "github.com/hashicorp/terraform-plugin-framework/datasource/schema" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" -) - -// Ensure provider defined types fully satisfy framework interfaces. -var _ datasource.DataSource = &FileDataSource{} -var _ datasource.DataSourceWithConfigure = &FileDataSource{} - -func NewFileDataSource() datasource.DataSource { - return &FileDataSource{} -} - -// FileDataSource is the data source implementation. -type FileDataSource struct { - client *sdk.SDK -} - -// FileDataSourceModel describes the data model. -type FileDataSourceModel struct { - AccessControl types.String `tfsdk:"access_control"` - ACL *tfTypes.BaseEntityACL `tfsdk:"acl"` - Additional map[string]types.String `tfsdk:"additional"` - Async types.Bool `tfsdk:"async"` - CreatedAt types.String `tfsdk:"created_at"` - CustomDownloadURL types.String `tfsdk:"custom_download_url"` - Filename types.String `tfsdk:"filename"` - ID types.String `tfsdk:"id"` - Manifest []types.String `tfsdk:"manifest"` - MimeType types.String `tfsdk:"mime_type"` - Org types.String `tfsdk:"org"` - Owners []tfTypes.BaseEntityOwner `tfsdk:"owners"` - PublicURL types.String `tfsdk:"public_url"` - Purpose []types.String `tfsdk:"purpose"` - ReadableSize types.String `tfsdk:"readable_size"` - S3ref *tfTypes.S3Ref `tfsdk:"s3ref"` - Schema types.String `tfsdk:"schema"` - SizeBytes types.Int64 `tfsdk:"size_bytes"` - SourceURL types.String `tfsdk:"source_url"` - Strict types.Bool `tfsdk:"strict"` - Tags []types.String `tfsdk:"tags"` - Title types.String `tfsdk:"title"` - Type types.String `tfsdk:"type"` - UpdatedAt types.String `tfsdk:"updated_at"` - Versions []tfTypes.FileItem `tfsdk:"versions"` -} - -// Metadata returns the data source type name. -func (r *FileDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { - resp.TypeName = req.ProviderTypeName + "_file" -} - -// Schema defines the schema for the data source. -func (r *FileDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - resp.Schema = schema.Schema{ - MarkdownDescription: "File DataSource", - - Attributes: map[string]schema.Attribute{ - "access_control": schema.StringAttribute{ - Computed: true, - }, - "acl": schema.SingleNestedAttribute{ - Computed: true, - Attributes: map[string]schema.Attribute{ - "delete": schema.ListAttribute{ - Computed: true, - ElementType: types.StringType, - }, - "edit": schema.ListAttribute{ - Computed: true, - ElementType: types.StringType, - }, - "view": schema.ListAttribute{ - Computed: true, - ElementType: types.StringType, - }, - }, - Description: `Access control list (ACL) for an entity. Defines sharing access to external orgs or users.`, - }, - "additional": schema.MapAttribute{ - Computed: true, - ElementType: types.StringType, - Description: `Additional fields that are not part of the schema`, - }, - "async": schema.BoolAttribute{ - Computed: true, - Optional: true, - Description: `Don't wait for updated entity to become available in Search API. Useful for large migrations`, - }, - "created_at": schema.StringAttribute{ - Computed: true, - }, - "custom_download_url": schema.StringAttribute{ - Computed: true, - Description: `Custom external download url used for the file`, - }, - "filename": schema.StringAttribute{ - Computed: true, - }, - "id": schema.StringAttribute{ - Required: true, - }, - "manifest": schema.ListAttribute{ - Computed: true, - ElementType: types.StringType, - Description: `Manifest ID used to create/update the entity`, - }, - "mime_type": schema.StringAttribute{ - Computed: true, - Description: `MIME type of the file`, - }, - "org": schema.StringAttribute{ - Computed: true, - }, - "owners": schema.ListNestedAttribute{ - Computed: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "org_id": schema.StringAttribute{ - Computed: true, - }, - "user_id": schema.StringAttribute{ - Computed: true, - }, - }, - }, - }, - "public_url": schema.StringAttribute{ - Computed: true, - Description: `Direct URL for file (public only if file access control is public-read)`, - }, - "purpose": schema.ListAttribute{ - Computed: true, - ElementType: types.StringType, - }, - "readable_size": schema.StringAttribute{ - Computed: true, - Description: `Human readable file size`, - }, - "s3ref": schema.SingleNestedAttribute{ - Computed: true, - Attributes: map[string]schema.Attribute{ - "bucket": schema.StringAttribute{ - Computed: true, - }, - "key": schema.StringAttribute{ - Computed: true, - }, - }, - }, - "schema": schema.StringAttribute{ - Computed: true, - }, - "size_bytes": schema.Int64Attribute{ - Computed: true, - Description: `File size in bytes`, - }, - "source_url": schema.StringAttribute{ - Computed: true, - Description: `Source URL for the file. Included if the entity was created from source_url, or when ?source_url=true`, - }, - "strict": schema.BoolAttribute{ - Computed: true, - Optional: true, - Description: `When passed true, the response will contain only fields that match the schema, with non-matching fields included in ` + "`" + `__additional` + "`" + ``, - }, - "tags": schema.ListAttribute{ - Computed: true, - ElementType: types.StringType, - }, - "title": schema.StringAttribute{ - Computed: true, - }, - "type": schema.StringAttribute{ - Computed: true, - }, - "updated_at": schema.StringAttribute{ - Computed: true, - }, - "versions": schema.ListNestedAttribute{ - Computed: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "filename": schema.StringAttribute{ - Computed: true, - }, - "mime_type": schema.StringAttribute{ - Computed: true, - }, - "readable_size": schema.StringAttribute{ - Computed: true, - }, - "s3ref": schema.SingleNestedAttribute{ - Computed: true, - Attributes: map[string]schema.Attribute{ - "bucket": schema.StringAttribute{ - Computed: true, - }, - "key": schema.StringAttribute{ - Computed: true, - }, - }, - }, - "size_bytes": schema.Int64Attribute{ - Computed: true, - }, - }, - }, - }, - }, - } -} - -func (r *FileDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { - // Prevent panic if the provider has not been configured. - if req.ProviderData == nil { - return - } - - client, ok := req.ProviderData.(*sdk.SDK) - - if !ok { - resp.Diagnostics.AddError( - "Unexpected DataSource Configure Type", - fmt.Sprintf("Expected *sdk.SDK, got: %T. Please report this issue to the provider developers.", req.ProviderData), - ) - - return - } - - r.client = client -} - -func (r *FileDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { - var data *FileDataSourceModel - var item types.Object - - resp.Diagnostics.Append(req.Config.Get(ctx, &item)...) - if resp.Diagnostics.HasError() { - return - } - - resp.Diagnostics.Append(item.As(ctx, &data, basetypes.ObjectAsOptions{ - UnhandledNullAsEmpty: true, - UnhandledUnknownAsEmpty: true, - })...) - - if resp.Diagnostics.HasError() { - return - } - - async := new(bool) - if !data.Async.IsUnknown() && !data.Async.IsNull() { - *async = data.Async.ValueBool() - } else { - async = nil - } - var id string - id = data.ID.ValueString() - - strict := new(bool) - if !data.Strict.IsUnknown() && !data.Strict.IsNull() { - *strict = data.Strict.ValueBool() - } else { - strict = nil - } - request := operations.GetFileRequest{ - Async: async, - ID: id, - Strict: strict, - } - res, err := r.client.File.GetFile(ctx, request) - if err != nil { - resp.Diagnostics.AddError("failure to invoke API", err.Error()) - if res != nil && res.RawResponse != nil { - resp.Diagnostics.AddError("unexpected http request/response", debugResponse(res.RawResponse)) - } - return - } - if res == nil { - resp.Diagnostics.AddError("unexpected response from API", fmt.Sprintf("%v", res)) - return - } - if res.StatusCode == 404 { - resp.State.RemoveResource(ctx) - return - } - if res.StatusCode != 200 { - resp.Diagnostics.AddError(fmt.Sprintf("unexpected response from API. Got an unexpected response code %v", res.StatusCode), debugResponse(res.RawResponse)) - return - } - if !(res.FileEntity != nil) { - resp.Diagnostics.AddError("unexpected response from API. Got an unexpected response body", debugResponse(res.RawResponse)) - return - } - data.RefreshFromSharedFileEntity(res.FileEntity) - - // Save updated data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) -} diff --git a/internal/provider/file_data_source_sdk.go b/internal/provider/file_data_source_sdk.go deleted file mode 100644 index 4d3623b..0000000 --- a/internal/provider/file_data_source_sdk.go +++ /dev/null @@ -1,136 +0,0 @@ -// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. - -package provider - -import ( - "encoding/json" - tfTypes "github.com/epilot-dev/terraform-provider-epilot-file/internal/provider/types" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/shared" - "github.com/hashicorp/terraform-plugin-framework/types" - "time" -) - -func (r *FileDataSourceModel) RefreshFromSharedFileEntity(resp *shared.FileEntity) { - if resp != nil { - if len(resp.Additional) > 0 { - r.Additional = make(map[string]types.String) - for key, value := range resp.Additional { - result, _ := json.Marshal(value) - r.Additional[key] = types.StringValue(string(result)) - } - } - if resp.ACL == nil { - r.ACL = nil - } else { - r.ACL = &tfTypes.BaseEntityACL{} - r.ACL.Delete = []types.String{} - for _, v := range resp.ACL.Delete { - r.ACL.Delete = append(r.ACL.Delete, types.StringValue(v)) - } - r.ACL.Edit = []types.String{} - for _, v := range resp.ACL.Edit { - r.ACL.Edit = append(r.ACL.Edit, types.StringValue(v)) - } - r.ACL.View = []types.String{} - for _, v := range resp.ACL.View { - r.ACL.View = append(r.ACL.View, types.StringValue(v)) - } - } - if resp.CreatedAt != nil { - r.CreatedAt = types.StringValue(resp.CreatedAt.Format(time.RFC3339Nano)) - } else { - r.CreatedAt = types.StringNull() - } - r.Manifest = []types.String{} - for _, v := range resp.Manifest { - r.Manifest = append(r.Manifest, types.StringValue(v)) - } - r.Org = types.StringPointerValue(resp.Org) - r.Owners = []tfTypes.BaseEntityOwner{} - if len(r.Owners) > len(resp.Owners) { - r.Owners = r.Owners[:len(resp.Owners)] - } - for ownersCount, ownersItem := range resp.Owners { - var owners1 tfTypes.BaseEntityOwner - owners1.OrgID = types.StringValue(ownersItem.OrgID) - owners1.UserID = types.StringPointerValue(ownersItem.UserID) - if ownersCount+1 > len(r.Owners) { - r.Owners = append(r.Owners, owners1) - } else { - r.Owners[ownersCount].OrgID = owners1.OrgID - r.Owners[ownersCount].UserID = owners1.UserID - } - } - r.Purpose = []types.String{} - for _, v := range resp.Purpose { - r.Purpose = append(r.Purpose, types.StringValue(v)) - } - if resp.Schema != nil { - r.Schema = types.StringValue(string(*resp.Schema)) - } else { - r.Schema = types.StringNull() - } - r.Tags = []types.String{} - for _, v := range resp.Tags { - r.Tags = append(r.Tags, types.StringValue(v)) - } - r.Title = types.StringPointerValue(resp.Title) - if resp.UpdatedAt != nil { - r.UpdatedAt = types.StringValue(resp.UpdatedAt.Format(time.RFC3339Nano)) - } else { - r.UpdatedAt = types.StringNull() - } - if resp.AccessControl != nil { - r.AccessControl = types.StringValue(string(*resp.AccessControl)) - } else { - r.AccessControl = types.StringNull() - } - r.CustomDownloadURL = types.StringPointerValue(resp.CustomDownloadURL) - r.Filename = types.StringPointerValue(resp.Filename) - r.ID = types.StringPointerValue(resp.ID) - r.MimeType = types.StringPointerValue(resp.MimeType) - r.PublicURL = types.StringPointerValue(resp.PublicURL) - r.ReadableSize = types.StringPointerValue(resp.ReadableSize) - if resp.S3ref == nil { - r.S3ref = nil - } else { - r.S3ref = &tfTypes.S3Ref{} - r.S3ref.Bucket = types.StringValue(resp.S3ref.Bucket) - r.S3ref.Key = types.StringValue(resp.S3ref.Key) - } - r.SizeBytes = types.Int64PointerValue(resp.SizeBytes) - r.SourceURL = types.StringPointerValue(resp.SourceURL) - if resp.Type != nil { - r.Type = types.StringValue(string(*resp.Type)) - } else { - r.Type = types.StringNull() - } - r.Versions = []tfTypes.FileItem{} - if len(r.Versions) > len(resp.Versions) { - r.Versions = r.Versions[:len(resp.Versions)] - } - for versionsCount, versionsItem := range resp.Versions { - var versions1 tfTypes.FileItem - versions1.Filename = types.StringPointerValue(versionsItem.Filename) - versions1.MimeType = types.StringPointerValue(versionsItem.MimeType) - versions1.ReadableSize = types.StringPointerValue(versionsItem.ReadableSize) - if versionsItem.S3ref == nil { - versions1.S3ref = nil - } else { - versions1.S3ref = &tfTypes.S3Ref{} - versions1.S3ref.Bucket = types.StringValue(versionsItem.S3ref.Bucket) - versions1.S3ref.Key = types.StringValue(versionsItem.S3ref.Key) - } - versions1.SizeBytes = types.Int64PointerValue(versionsItem.SizeBytes) - if versionsCount+1 > len(r.Versions) { - r.Versions = append(r.Versions, versions1) - } else { - r.Versions[versionsCount].Filename = versions1.Filename - r.Versions[versionsCount].MimeType = versions1.MimeType - r.Versions[versionsCount].ReadableSize = versions1.ReadableSize - r.Versions[versionsCount].S3ref = versions1.S3ref - r.Versions[versionsCount].SizeBytes = versions1.SizeBytes - } - } - } -} diff --git a/internal/provider/file_resource.go b/internal/provider/file_resource.go deleted file mode 100644 index 8f0a083..0000000 --- a/internal/provider/file_resource.go +++ /dev/null @@ -1,815 +0,0 @@ -// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. - -package provider - -import ( - "context" - "fmt" - speakeasy_int64planmodifier "github.com/epilot-dev/terraform-provider-epilot-file/internal/planmodifiers/int64planmodifier" - speakeasy_listplanmodifier "github.com/epilot-dev/terraform-provider-epilot-file/internal/planmodifiers/listplanmodifier" - speakeasy_mapplanmodifier "github.com/epilot-dev/terraform-provider-epilot-file/internal/planmodifiers/mapplanmodifier" - speakeasy_objectplanmodifier "github.com/epilot-dev/terraform-provider-epilot-file/internal/planmodifiers/objectplanmodifier" - speakeasy_stringplanmodifier "github.com/epilot-dev/terraform-provider-epilot-file/internal/planmodifiers/stringplanmodifier" - tfTypes "github.com/epilot-dev/terraform-provider-epilot-file/internal/provider/types" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/operations" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/validators" - speakeasy_stringvalidators "github.com/epilot-dev/terraform-provider-epilot-file/internal/validators/stringvalidators" - "github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator" - "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" - "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/resource" - "github.com/hashicorp/terraform-plugin-framework/resource/schema" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" - "github.com/hashicorp/terraform-plugin-framework/schema/validator" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" -) - -// Ensure provider defined types fully satisfy framework interfaces. -var _ resource.Resource = &FileResource{} -var _ resource.ResourceWithImportState = &FileResource{} - -func NewFileResource() resource.Resource { - return &FileResource{} -} - -// FileResource defines the resource implementation. -type FileResource struct { - client *sdk.SDK -} - -// FileResourceModel describes the resource data model. -type FileResourceModel struct { - AccessControl types.String `tfsdk:"access_control"` - ACL *tfTypes.BaseEntityACL `tfsdk:"acl"` - ActivityID types.String `tfsdk:"activity_id"` - Additional map[string]types.String `tfsdk:"additional"` - Async types.Bool `tfsdk:"async"` - CreatedAt types.String `tfsdk:"created_at"` - CustomDownloadURL types.String `tfsdk:"custom_download_url"` - Filename types.String `tfsdk:"filename"` - FillActivity types.Bool `tfsdk:"fill_activity"` - ID types.String `tfsdk:"id"` - Manifest []types.String `tfsdk:"manifest"` - MimeType types.String `tfsdk:"mime_type"` - Org types.String `tfsdk:"org"` - Owners []tfTypes.BaseEntityOwner `tfsdk:"owners"` - PublicURL types.String `tfsdk:"public_url"` - Purpose []types.String `tfsdk:"purpose"` - ReadableSize types.String `tfsdk:"readable_size"` - S3ref *tfTypes.S3Ref `tfsdk:"s3ref"` - Schema types.String `tfsdk:"schema"` - SizeBytes types.Int64 `tfsdk:"size_bytes"` - SourceURL types.String `tfsdk:"source_url"` - Strict types.Bool `tfsdk:"strict"` - Tags []types.String `tfsdk:"tags"` - Title types.String `tfsdk:"title"` - Type types.String `tfsdk:"type"` - UpdatedAt types.String `tfsdk:"updated_at"` - Versions []tfTypes.FileItem `tfsdk:"versions"` -} - -func (r *FileResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { - resp.TypeName = req.ProviderTypeName + "_file" -} - -func (r *FileResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema = schema.Schema{ - MarkdownDescription: "File Resource", - Attributes: map[string]schema.Attribute{ - "access_control": schema.StringAttribute{ - Computed: true, - Optional: true, - Default: stringdefault.StaticString("private"), - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Description: `Default: "private"; must be one of ["private", "public-read"]`, - Validators: []validator.String{ - stringvalidator.OneOf( - "private", - "public-read", - ), - }, - }, - "acl": schema.SingleNestedAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.Object{ - speakeasy_objectplanmodifier.SuppressDiff(speakeasy_objectplanmodifier.ExplicitSuppress), - }, - Attributes: map[string]schema.Attribute{ - "delete": schema.ListAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.List{ - speakeasy_listplanmodifier.SuppressDiff(speakeasy_listplanmodifier.ExplicitSuppress), - }, - ElementType: types.StringType, - }, - "edit": schema.ListAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.List{ - speakeasy_listplanmodifier.SuppressDiff(speakeasy_listplanmodifier.ExplicitSuppress), - }, - ElementType: types.StringType, - }, - "view": schema.ListAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.List{ - speakeasy_listplanmodifier.SuppressDiff(speakeasy_listplanmodifier.ExplicitSuppress), - }, - ElementType: types.StringType, - }, - }, - Description: `Access control list (ACL) for an entity. Defines sharing access to external orgs or users.`, - }, - "activity_id": schema.StringAttribute{ - Optional: true, - Description: `Activity to include in event feed`, - }, - "additional": schema.MapAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.Map{ - speakeasy_mapplanmodifier.SuppressDiff(speakeasy_mapplanmodifier.ExplicitSuppress), - }, - ElementType: types.StringType, - Description: `Additional fields that are not part of the schema`, - Validators: []validator.Map{ - mapvalidator.ValueStringsAre(validators.IsValidJSON()), - }, - }, - "async": schema.BoolAttribute{ - Computed: true, - Optional: true, - Default: booldefault.StaticBool(false), - Description: `Don't wait for updated entity to become available in Search API. Useful for large migrations. Default: false`, - }, - "created_at": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Validators: []validator.String{ - validators.IsRFC3339(), - }, - }, - "custom_download_url": schema.StringAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Description: `Custom external download url used for the file`, - }, - "filename": schema.StringAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - }, - "fill_activity": schema.BoolAttribute{ - Computed: true, - Optional: true, - Default: booldefault.StaticBool(false), - MarkdownDescription: `Update the diff and entity for the custom activity included in the query.` + "\n" + - `Pending state on activity is automatically ended when activity is filled.` + "\n" + - `Default: false`, - }, - "id": schema.StringAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - }, - "manifest": schema.ListAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.List{ - speakeasy_listplanmodifier.SuppressDiff(speakeasy_listplanmodifier.ExplicitSuppress), - }, - ElementType: types.StringType, - Description: `Manifest ID used to create/update the entity`, - }, - "mime_type": schema.StringAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Description: `MIME type of the file`, - }, - "org": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - }, - "owners": schema.ListNestedAttribute{ - Computed: true, - PlanModifiers: []planmodifier.List{ - speakeasy_listplanmodifier.SuppressDiff(speakeasy_listplanmodifier.ExplicitSuppress), - }, - NestedObject: schema.NestedAttributeObject{ - PlanModifiers: []planmodifier.Object{ - speakeasy_objectplanmodifier.SuppressDiff(speakeasy_objectplanmodifier.ExplicitSuppress), - }, - Attributes: map[string]schema.Attribute{ - "org_id": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - }, - "user_id": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - }, - }, - }, - }, - "public_url": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Description: `Direct URL for file (public only if file access control is public-read)`, - }, - "purpose": schema.ListAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.List{ - speakeasy_listplanmodifier.SuppressDiff(speakeasy_listplanmodifier.ExplicitSuppress), - }, - ElementType: types.StringType, - }, - "readable_size": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Description: `Human readable file size`, - }, - "s3ref": schema.SingleNestedAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.Object{ - speakeasy_objectplanmodifier.SuppressDiff(speakeasy_objectplanmodifier.ExplicitSuppress), - }, - Attributes: map[string]schema.Attribute{ - "bucket": schema.StringAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Description: `Not Null`, - Validators: []validator.String{ - speakeasy_stringvalidators.NotNull(), - }, - }, - "key": schema.StringAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Description: `Not Null`, - Validators: []validator.String{ - speakeasy_stringvalidators.NotNull(), - }, - }, - }, - }, - "schema": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Description: `must be "file"`, - Validators: []validator.String{ - stringvalidator.OneOf("file"), - }, - }, - "size_bytes": schema.Int64Attribute{ - Computed: true, - PlanModifiers: []planmodifier.Int64{ - speakeasy_int64planmodifier.SuppressDiff(speakeasy_int64planmodifier.ExplicitSuppress), - }, - Description: `File size in bytes`, - }, - "source_url": schema.StringAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Description: `Source URL for the file. Included if the entity was created from source_url, or when ?source_url=true`, - }, - "strict": schema.BoolAttribute{ - Computed: true, - Optional: true, - Default: booldefault.StaticBool(false), - Description: `When passed true, the response will contain only fields that match the schema, with non-matching fields included in ` + "`" + `__additional` + "`" + `. Default: false`, - }, - "tags": schema.ListAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.List{ - speakeasy_listplanmodifier.SuppressDiff(speakeasy_listplanmodifier.ExplicitSuppress), - }, - ElementType: types.StringType, - }, - "title": schema.StringAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - }, - "type": schema.StringAttribute{ - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Description: `must be one of ["document", "document_template", "text", "image", "video", "audio", "spreadsheet", "presentation", "font", "archive", "application", "unknown"]`, - Validators: []validator.String{ - stringvalidator.OneOf( - "document", - "document_template", - "text", - "image", - "video", - "audio", - "spreadsheet", - "presentation", - "font", - "archive", - "application", - "unknown", - ), - }, - }, - "updated_at": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - Validators: []validator.String{ - validators.IsRFC3339(), - }, - }, - "versions": schema.ListNestedAttribute{ - Computed: true, - PlanModifiers: []planmodifier.List{ - speakeasy_listplanmodifier.SuppressDiff(speakeasy_listplanmodifier.ExplicitSuppress), - }, - NestedObject: schema.NestedAttributeObject{ - PlanModifiers: []planmodifier.Object{ - speakeasy_objectplanmodifier.SuppressDiff(speakeasy_objectplanmodifier.ExplicitSuppress), - }, - Attributes: map[string]schema.Attribute{ - "filename": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - }, - "mime_type": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - }, - "readable_size": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - }, - "s3ref": schema.SingleNestedAttribute{ - Computed: true, - PlanModifiers: []planmodifier.Object{ - speakeasy_objectplanmodifier.SuppressDiff(speakeasy_objectplanmodifier.ExplicitSuppress), - }, - Attributes: map[string]schema.Attribute{ - "bucket": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - }, - "key": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - speakeasy_stringplanmodifier.SuppressDiff(speakeasy_stringplanmodifier.ExplicitSuppress), - }, - }, - }, - }, - "size_bytes": schema.Int64Attribute{ - Computed: true, - PlanModifiers: []planmodifier.Int64{ - speakeasy_int64planmodifier.SuppressDiff(speakeasy_int64planmodifier.ExplicitSuppress), - }, - }, - }, - }, - }, - }, - } -} - -func (r *FileResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { - // Prevent panic if the provider has not been configured. - if req.ProviderData == nil { - return - } - - client, ok := req.ProviderData.(*sdk.SDK) - - if !ok { - resp.Diagnostics.AddError( - "Unexpected Resource Configure Type", - fmt.Sprintf("Expected *sdk.SDK, got: %T. Please report this issue to the provider developers.", req.ProviderData), - ) - - return - } - - r.client = client -} - -func (r *FileResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - var data *FileResourceModel - var plan types.Object - - resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) - if resp.Diagnostics.HasError() { - return - } - - resp.Diagnostics.Append(plan.As(ctx, &data, basetypes.ObjectAsOptions{ - UnhandledNullAsEmpty: true, - UnhandledUnknownAsEmpty: true, - })...) - - if resp.Diagnostics.HasError() { - return - } - - saveFilePayloadV2 := data.ToSharedSaveFilePayloadV2() - activityID := new(string) - if !data.ActivityID.IsUnknown() && !data.ActivityID.IsNull() { - *activityID = data.ActivityID.ValueString() - } else { - activityID = nil - } - async := new(bool) - if !data.Async.IsUnknown() && !data.Async.IsNull() { - *async = data.Async.ValueBool() - } else { - async = nil - } - fillActivity := new(bool) - if !data.FillActivity.IsUnknown() && !data.FillActivity.IsNull() { - *fillActivity = data.FillActivity.ValueBool() - } else { - fillActivity = nil - } - strict := new(bool) - if !data.Strict.IsUnknown() && !data.Strict.IsNull() { - *strict = data.Strict.ValueBool() - } else { - strict = nil - } - request := operations.SaveFileV2Request{ - SaveFilePayloadV2: saveFilePayloadV2, - ActivityID: activityID, - Async: async, - FillActivity: fillActivity, - Strict: strict, - } - res, err := r.client.File.SaveFileV2(ctx, request) - if err != nil { - resp.Diagnostics.AddError("failure to invoke API", err.Error()) - if res != nil && res.RawResponse != nil { - resp.Diagnostics.AddError("unexpected http request/response", debugResponse(res.RawResponse)) - } - return - } - if res == nil { - resp.Diagnostics.AddError("unexpected response from API", fmt.Sprintf("%v", res)) - return - } - if res.StatusCode != 200 { - resp.Diagnostics.AddError(fmt.Sprintf("unexpected response from API. Got an unexpected response code %v", res.StatusCode), debugResponse(res.RawResponse)) - return - } - if !(res.FileEntity != nil) { - resp.Diagnostics.AddError("unexpected response from API. Got an unexpected response body", debugResponse(res.RawResponse)) - return - } - data.RefreshFromSharedFileEntity(res.FileEntity) - refreshPlan(ctx, plan, &data, resp.Diagnostics) - async1 := new(bool) - if !data.Async.IsUnknown() && !data.Async.IsNull() { - *async1 = data.Async.ValueBool() - } else { - async1 = nil - } - var id string - id = data.ID.ValueString() - - strict1 := new(bool) - if !data.Strict.IsUnknown() && !data.Strict.IsNull() { - *strict1 = data.Strict.ValueBool() - } else { - strict1 = nil - } - request1 := operations.GetFileRequest{ - Async: async1, - ID: id, - Strict: strict1, - } - res1, err := r.client.File.GetFile(ctx, request1) - if err != nil { - resp.Diagnostics.AddError("failure to invoke API", err.Error()) - if res1 != nil && res1.RawResponse != nil { - resp.Diagnostics.AddError("unexpected http request/response", debugResponse(res1.RawResponse)) - } - return - } - if res1 == nil { - resp.Diagnostics.AddError("unexpected response from API", fmt.Sprintf("%v", res1)) - return - } - if res1.StatusCode != 200 { - resp.Diagnostics.AddError(fmt.Sprintf("unexpected response from API. Got an unexpected response code %v", res1.StatusCode), debugResponse(res1.RawResponse)) - return - } - if !(res1.FileEntity != nil) { - resp.Diagnostics.AddError("unexpected response from API. Got an unexpected response body", debugResponse(res1.RawResponse)) - return - } - data.RefreshFromSharedFileEntity(res1.FileEntity) - refreshPlan(ctx, plan, &data, resp.Diagnostics) - - // Save updated data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) -} - -func (r *FileResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - var data *FileResourceModel - var item types.Object - - resp.Diagnostics.Append(req.State.Get(ctx, &item)...) - if resp.Diagnostics.HasError() { - return - } - - resp.Diagnostics.Append(item.As(ctx, &data, basetypes.ObjectAsOptions{ - UnhandledNullAsEmpty: true, - UnhandledUnknownAsEmpty: true, - })...) - - if resp.Diagnostics.HasError() { - return - } - - async := new(bool) - if !data.Async.IsUnknown() && !data.Async.IsNull() { - *async = data.Async.ValueBool() - } else { - async = nil - } - var id string - id = data.ID.ValueString() - - strict := new(bool) - if !data.Strict.IsUnknown() && !data.Strict.IsNull() { - *strict = data.Strict.ValueBool() - } else { - strict = nil - } - request := operations.GetFileRequest{ - Async: async, - ID: id, - Strict: strict, - } - res, err := r.client.File.GetFile(ctx, request) - if err != nil { - resp.Diagnostics.AddError("failure to invoke API", err.Error()) - if res != nil && res.RawResponse != nil { - resp.Diagnostics.AddError("unexpected http request/response", debugResponse(res.RawResponse)) - } - return - } - if res == nil { - resp.Diagnostics.AddError("unexpected response from API", fmt.Sprintf("%v", res)) - return - } - if res.StatusCode == 404 { - resp.State.RemoveResource(ctx) - return - } - if res.StatusCode != 200 { - resp.Diagnostics.AddError(fmt.Sprintf("unexpected response from API. Got an unexpected response code %v", res.StatusCode), debugResponse(res.RawResponse)) - return - } - if !(res.FileEntity != nil) { - resp.Diagnostics.AddError("unexpected response from API. Got an unexpected response body", debugResponse(res.RawResponse)) - return - } - data.RefreshFromSharedFileEntity(res.FileEntity) - - // Save updated data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) -} - -func (r *FileResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { - var data *FileResourceModel - var plan types.Object - - resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) - if resp.Diagnostics.HasError() { - return - } - - merge(ctx, req, resp, &data) - if resp.Diagnostics.HasError() { - return - } - - saveFilePayloadV2 := data.ToSharedSaveFilePayloadV2() - activityID := new(string) - if !data.ActivityID.IsUnknown() && !data.ActivityID.IsNull() { - *activityID = data.ActivityID.ValueString() - } else { - activityID = nil - } - async := new(bool) - if !data.Async.IsUnknown() && !data.Async.IsNull() { - *async = data.Async.ValueBool() - } else { - async = nil - } - fillActivity := new(bool) - if !data.FillActivity.IsUnknown() && !data.FillActivity.IsNull() { - *fillActivity = data.FillActivity.ValueBool() - } else { - fillActivity = nil - } - strict := new(bool) - if !data.Strict.IsUnknown() && !data.Strict.IsNull() { - *strict = data.Strict.ValueBool() - } else { - strict = nil - } - request := operations.SaveFileV2Request{ - SaveFilePayloadV2: saveFilePayloadV2, - ActivityID: activityID, - Async: async, - FillActivity: fillActivity, - Strict: strict, - } - res, err := r.client.File.SaveFileV2(ctx, request) - if err != nil { - resp.Diagnostics.AddError("failure to invoke API", err.Error()) - if res != nil && res.RawResponse != nil { - resp.Diagnostics.AddError("unexpected http request/response", debugResponse(res.RawResponse)) - } - return - } - if res == nil { - resp.Diagnostics.AddError("unexpected response from API", fmt.Sprintf("%v", res)) - return - } - if res.StatusCode != 200 { - resp.Diagnostics.AddError(fmt.Sprintf("unexpected response from API. Got an unexpected response code %v", res.StatusCode), debugResponse(res.RawResponse)) - return - } - if !(res.FileEntity != nil) { - resp.Diagnostics.AddError("unexpected response from API. Got an unexpected response body", debugResponse(res.RawResponse)) - return - } - data.RefreshFromSharedFileEntity(res.FileEntity) - refreshPlan(ctx, plan, &data, resp.Diagnostics) - async1 := new(bool) - if !data.Async.IsUnknown() && !data.Async.IsNull() { - *async1 = data.Async.ValueBool() - } else { - async1 = nil - } - var id string - id = data.ID.ValueString() - - strict1 := new(bool) - if !data.Strict.IsUnknown() && !data.Strict.IsNull() { - *strict1 = data.Strict.ValueBool() - } else { - strict1 = nil - } - request1 := operations.GetFileRequest{ - Async: async1, - ID: id, - Strict: strict1, - } - res1, err := r.client.File.GetFile(ctx, request1) - if err != nil { - resp.Diagnostics.AddError("failure to invoke API", err.Error()) - if res1 != nil && res1.RawResponse != nil { - resp.Diagnostics.AddError("unexpected http request/response", debugResponse(res1.RawResponse)) - } - return - } - if res1 == nil { - resp.Diagnostics.AddError("unexpected response from API", fmt.Sprintf("%v", res1)) - return - } - if res1.StatusCode != 200 { - resp.Diagnostics.AddError(fmt.Sprintf("unexpected response from API. Got an unexpected response code %v", res1.StatusCode), debugResponse(res1.RawResponse)) - return - } - if !(res1.FileEntity != nil) { - resp.Diagnostics.AddError("unexpected response from API. Got an unexpected response body", debugResponse(res1.RawResponse)) - return - } - data.RefreshFromSharedFileEntity(res1.FileEntity) - refreshPlan(ctx, plan, &data, resp.Diagnostics) - - // Save updated data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) -} - -func (r *FileResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - var data *FileResourceModel - var item types.Object - - resp.Diagnostics.Append(req.State.Get(ctx, &item)...) - if resp.Diagnostics.HasError() { - return - } - - resp.Diagnostics.Append(item.As(ctx, &data, basetypes.ObjectAsOptions{ - UnhandledNullAsEmpty: true, - UnhandledUnknownAsEmpty: true, - })...) - - if resp.Diagnostics.HasError() { - return - } - - activityID := new(string) - if !data.ActivityID.IsUnknown() && !data.ActivityID.IsNull() { - *activityID = data.ActivityID.ValueString() - } else { - activityID = nil - } - var id string - id = data.ID.ValueString() - - strict := new(bool) - if !data.Strict.IsUnknown() && !data.Strict.IsNull() { - *strict = data.Strict.ValueBool() - } else { - strict = nil - } - request := operations.DeleteFileRequest{ - ActivityID: activityID, - ID: id, - Strict: strict, - } - res, err := r.client.File.DeleteFile(ctx, request) - if err != nil { - resp.Diagnostics.AddError("failure to invoke API", err.Error()) - if res != nil && res.RawResponse != nil { - resp.Diagnostics.AddError("unexpected http request/response", debugResponse(res.RawResponse)) - } - return - } - if res == nil { - resp.Diagnostics.AddError("unexpected response from API", fmt.Sprintf("%v", res)) - return - } - if res.StatusCode != 200 { - resp.Diagnostics.AddError(fmt.Sprintf("unexpected response from API. Got an unexpected response code %v", res.StatusCode), debugResponse(res.RawResponse)) - return - } - -} - -func (r *FileResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), req.ID)...) -} diff --git a/internal/provider/file_resource_sdk.go b/internal/provider/file_resource_sdk.go deleted file mode 100644 index 06866a3..0000000 --- a/internal/provider/file_resource_sdk.go +++ /dev/null @@ -1,255 +0,0 @@ -// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. - -package provider - -import ( - "encoding/json" - tfTypes "github.com/epilot-dev/terraform-provider-epilot-file/internal/provider/types" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/shared" - "github.com/hashicorp/terraform-plugin-framework/types" - "time" -) - -func (r *FileResourceModel) ToSharedSaveFilePayloadV2() *shared.SaveFilePayloadV2 { - additional := make(map[string]interface{}) - for additionalKey, additionalValue := range r.Additional { - var additionalInst interface{} - _ = json.Unmarshal([]byte(additionalValue.ValueString()), &additionalInst) - additional[additionalKey] = additionalInst - } - var acl *shared.BaseEntityACL - if r.ACL != nil { - var delete []string = []string{} - for _, deleteItem := range r.ACL.Delete { - delete = append(delete, deleteItem.ValueString()) - } - var edit []string = []string{} - for _, editItem := range r.ACL.Edit { - edit = append(edit, editItem.ValueString()) - } - var view []string = []string{} - for _, viewItem := range r.ACL.View { - view = append(view, viewItem.ValueString()) - } - acl = &shared.BaseEntityACL{ - Delete: delete, - Edit: edit, - View: view, - } - } - id := new(string) - if !r.ID.IsUnknown() && !r.ID.IsNull() { - *id = r.ID.ValueString() - } else { - id = nil - } - var manifest []string = []string{} - for _, manifestItem := range r.Manifest { - manifest = append(manifest, manifestItem.ValueString()) - } - var purpose []string = []string{} - for _, purposeItem := range r.Purpose { - purpose = append(purpose, purposeItem.ValueString()) - } - var tags []string = []string{} - for _, tagsItem := range r.Tags { - tags = append(tags, tagsItem.ValueString()) - } - title := new(string) - if !r.Title.IsUnknown() && !r.Title.IsNull() { - *title = r.Title.ValueString() - } else { - title = nil - } - accessControl := new(shared.SaveFilePayloadV2AccessControl) - if !r.AccessControl.IsUnknown() && !r.AccessControl.IsNull() { - *accessControl = shared.SaveFilePayloadV2AccessControl(r.AccessControl.ValueString()) - } else { - accessControl = nil - } - customDownloadURL := new(string) - if !r.CustomDownloadURL.IsUnknown() && !r.CustomDownloadURL.IsNull() { - *customDownloadURL = r.CustomDownloadURL.ValueString() - } else { - customDownloadURL = nil - } - filename := new(string) - if !r.Filename.IsUnknown() && !r.Filename.IsNull() { - *filename = r.Filename.ValueString() - } else { - filename = nil - } - mimeType := new(string) - if !r.MimeType.IsUnknown() && !r.MimeType.IsNull() { - *mimeType = r.MimeType.ValueString() - } else { - mimeType = nil - } - var s3ref *shared.S3Ref - if r.S3ref != nil { - var bucket string - bucket = r.S3ref.Bucket.ValueString() - - var key string - key = r.S3ref.Key.ValueString() - - s3ref = &shared.S3Ref{ - Bucket: bucket, - Key: key, - } - } - sourceURL := new(string) - if !r.SourceURL.IsUnknown() && !r.SourceURL.IsNull() { - *sourceURL = r.SourceURL.ValueString() - } else { - sourceURL = nil - } - typeVar := new(shared.FileType) - if !r.Type.IsUnknown() && !r.Type.IsNull() { - *typeVar = shared.FileType(r.Type.ValueString()) - } else { - typeVar = nil - } - out := shared.SaveFilePayloadV2{ - Additional: additional, - ACL: acl, - ID: id, - Manifest: manifest, - Purpose: purpose, - Tags: tags, - Title: title, - AccessControl: accessControl, - CustomDownloadURL: customDownloadURL, - Filename: filename, - MimeType: mimeType, - S3ref: s3ref, - SourceURL: sourceURL, - Type: typeVar, - } - return &out -} - -func (r *FileResourceModel) RefreshFromSharedFileEntity(resp *shared.FileEntity) { - if resp != nil { - if len(resp.Additional) > 0 { - r.Additional = make(map[string]types.String) - for key, value := range resp.Additional { - result, _ := json.Marshal(value) - r.Additional[key] = types.StringValue(string(result)) - } - } - if resp.ACL == nil { - r.ACL = nil - } else { - r.ACL = &tfTypes.BaseEntityACL{} - r.ACL.Delete = []types.String{} - for _, v := range resp.ACL.Delete { - r.ACL.Delete = append(r.ACL.Delete, types.StringValue(v)) - } - r.ACL.Edit = []types.String{} - for _, v := range resp.ACL.Edit { - r.ACL.Edit = append(r.ACL.Edit, types.StringValue(v)) - } - r.ACL.View = []types.String{} - for _, v := range resp.ACL.View { - r.ACL.View = append(r.ACL.View, types.StringValue(v)) - } - } - if resp.CreatedAt != nil { - r.CreatedAt = types.StringValue(resp.CreatedAt.Format(time.RFC3339Nano)) - } else { - r.CreatedAt = types.StringNull() - } - r.ID = types.StringPointerValue(resp.ID) - r.Manifest = []types.String{} - for _, v := range resp.Manifest { - r.Manifest = append(r.Manifest, types.StringValue(v)) - } - r.Org = types.StringPointerValue(resp.Org) - r.Owners = []tfTypes.BaseEntityOwner{} - if len(r.Owners) > len(resp.Owners) { - r.Owners = r.Owners[:len(resp.Owners)] - } - for ownersCount, ownersItem := range resp.Owners { - var owners1 tfTypes.BaseEntityOwner - owners1.OrgID = types.StringValue(ownersItem.OrgID) - owners1.UserID = types.StringPointerValue(ownersItem.UserID) - if ownersCount+1 > len(r.Owners) { - r.Owners = append(r.Owners, owners1) - } else { - r.Owners[ownersCount].OrgID = owners1.OrgID - r.Owners[ownersCount].UserID = owners1.UserID - } - } - r.Purpose = []types.String{} - for _, v := range resp.Purpose { - r.Purpose = append(r.Purpose, types.StringValue(v)) - } - if resp.Schema != nil { - r.Schema = types.StringValue(string(*resp.Schema)) - } else { - r.Schema = types.StringNull() - } - r.Tags = []types.String{} - for _, v := range resp.Tags { - r.Tags = append(r.Tags, types.StringValue(v)) - } - r.Title = types.StringPointerValue(resp.Title) - if resp.UpdatedAt != nil { - r.UpdatedAt = types.StringValue(resp.UpdatedAt.Format(time.RFC3339Nano)) - } else { - r.UpdatedAt = types.StringNull() - } - if resp.AccessControl != nil { - r.AccessControl = types.StringValue(string(*resp.AccessControl)) - } else { - r.AccessControl = types.StringNull() - } - r.CustomDownloadURL = types.StringPointerValue(resp.CustomDownloadURL) - r.Filename = types.StringPointerValue(resp.Filename) - r.MimeType = types.StringPointerValue(resp.MimeType) - r.PublicURL = types.StringPointerValue(resp.PublicURL) - r.ReadableSize = types.StringPointerValue(resp.ReadableSize) - if resp.S3ref == nil { - r.S3ref = nil - } else { - r.S3ref = &tfTypes.S3Ref{} - r.S3ref.Bucket = types.StringValue(resp.S3ref.Bucket) - r.S3ref.Key = types.StringValue(resp.S3ref.Key) - } - r.SizeBytes = types.Int64PointerValue(resp.SizeBytes) - r.SourceURL = types.StringPointerValue(resp.SourceURL) - if resp.Type != nil { - r.Type = types.StringValue(string(*resp.Type)) - } else { - r.Type = types.StringNull() - } - r.Versions = []tfTypes.FileItem{} - if len(r.Versions) > len(resp.Versions) { - r.Versions = r.Versions[:len(resp.Versions)] - } - for versionsCount, versionsItem := range resp.Versions { - var versions1 tfTypes.FileItem - versions1.Filename = types.StringPointerValue(versionsItem.Filename) - versions1.MimeType = types.StringPointerValue(versionsItem.MimeType) - versions1.ReadableSize = types.StringPointerValue(versionsItem.ReadableSize) - if versionsItem.S3ref == nil { - versions1.S3ref = nil - } else { - versions1.S3ref = &tfTypes.S3Ref{} - versions1.S3ref.Bucket = types.StringValue(versionsItem.S3ref.Bucket) - versions1.S3ref.Key = types.StringValue(versionsItem.S3ref.Key) - } - versions1.SizeBytes = types.Int64PointerValue(versionsItem.SizeBytes) - if versionsCount+1 > len(r.Versions) { - r.Versions = append(r.Versions, versions1) - } else { - r.Versions[versionsCount].Filename = versions1.Filename - r.Versions[versionsCount].MimeType = versions1.MimeType - r.Versions[versionsCount].ReadableSize = versions1.ReadableSize - r.Versions[versionsCount].S3ref = versions1.S3ref - r.Versions[versionsCount].SizeBytes = versions1.SizeBytes - } - } - } -} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 958bb36..ae3d93f 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -7,6 +7,7 @@ import ( "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/shared" "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/ephemeral" "github.com/hashicorp/terraform-plugin-framework/provider" "github.com/hashicorp/terraform-plugin-framework/provider/schema" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -14,7 +15,8 @@ import ( "net/http" ) -var _ provider.Provider = &EpilotFileProvider{} +var _ provider.Provider = (*EpilotFileProvider)(nil) +var _ provider.ProviderWithEphemeralResources = (*EpilotFileProvider)(nil) type EpilotFileProvider struct { // version is set to the provider version on release, "dev" when the @@ -25,9 +27,9 @@ type EpilotFileProvider struct { // EpilotFileProviderModel describes the provider data model. type EpilotFileProviderModel struct { - ServerURL types.String `tfsdk:"server_url"` CookieAuth types.String `tfsdk:"cookie_auth"` EpilotAuth types.String `tfsdk:"epilot_auth"` + ServerURL types.String `tfsdk:"server_url"` } func (p *EpilotFileProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) { @@ -37,22 +39,21 @@ func (p *EpilotFileProvider) Metadata(ctx context.Context, req provider.Metadata func (p *EpilotFileProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) { resp.Schema = schema.Schema{ - Description: `File API: Upload and manage epilot Files`, Attributes: map[string]schema.Attribute{ - "server_url": schema.StringAttribute{ - MarkdownDescription: "Server URL (defaults to https://file.sls.epilot.io)", - Optional: true, - Required: false, - }, "cookie_auth": schema.StringAttribute{ - Sensitive: true, Optional: true, + Sensitive: true, }, "epilot_auth": schema.StringAttribute{ - Sensitive: true, Optional: true, + Sensitive: true, + }, + "server_url": schema.StringAttribute{ + Description: `Server URL (defaults to https://file.sls.epilot.io)`, + Optional: true, }, }, + MarkdownDescription: `File API: Upload and manage epilot Files`, } } @@ -88,27 +89,36 @@ func (p *EpilotFileProvider) Configure(ctx context.Context, req provider.Configu EpilotAuth: epilotAuth, } + providerHTTPTransportOpts := ProviderHTTPTransportOpts{ + SetHeaders: make(map[string]string), + Transport: http.DefaultTransport, + } + + httpClient := http.DefaultClient + httpClient.Transport = NewProviderHTTPTransport(providerHTTPTransportOpts) + opts := []sdk.SDKOption{ sdk.WithServerURL(ServerURL), sdk.WithSecurity(security), - sdk.WithClient(http.DefaultClient), + sdk.WithClient(httpClient), } client := sdk.New(opts...) resp.DataSourceData = client + resp.EphemeralResourceData = client resp.ResourceData = client } func (p *EpilotFileProvider) Resources(ctx context.Context) []func() resource.Resource { - return []func() resource.Resource{ - NewFileResource, - } + return []func() resource.Resource{} } func (p *EpilotFileProvider) DataSources(ctx context.Context) []func() datasource.DataSource { - return []func() datasource.DataSource{ - NewFileDataSource, - } + return []func() datasource.DataSource{} +} + +func (p *EpilotFileProvider) EphemeralResources(ctx context.Context) []func() ephemeral.EphemeralResource { + return []func() ephemeral.EphemeralResource{} } func New(version string) func() provider.Provider { diff --git a/internal/provider/reflect/helpers.go b/internal/provider/reflect/helpers.go index b17719d..8085789 100644 --- a/internal/provider/reflect/helpers.go +++ b/internal/provider/reflect/helpers.go @@ -46,7 +46,7 @@ func commaSeparatedString(in []string) string { // getStructTags returns a map of Terraform field names to their position in // the tags of the struct `in`. `in` must be a struct. -func getStructTags(_ context.Context, in reflect.Value, path path.Path, opts Options) (map[string]int, error) { +func getStructTags(_ context.Context, in reflect.Value, path path.Path, _ Options) (map[string]int, error) { tags := map[string]int{} typ := trueReflectValue(in).Type() if typ.Kind() != reflect.Struct { diff --git a/internal/provider/typeconvert/date.go b/internal/provider/typeconvert/date.go new file mode 100644 index 0000000..146c6f2 --- /dev/null +++ b/internal/provider/typeconvert/date.go @@ -0,0 +1,23 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package typeconvert + +import ( + sdkTypes "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/types" +) + +// Converts a date types.Date to string. +func DateToString(value sdkTypes.Date) string { + return value.String() +} + +// Converts a date *types.Date to *string. +func DatePointerToStringPointer(value *sdkTypes.Date) *string { + if value == nil { + return nil + } + + stringValue := DateToString(*value) + + return &stringValue +} diff --git a/internal/provider/typeconvert/datetime.go b/internal/provider/typeconvert/datetime.go new file mode 100644 index 0000000..7bfdc55 --- /dev/null +++ b/internal/provider/typeconvert/datetime.go @@ -0,0 +1,23 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package typeconvert + +import ( + "time" +) + +// Converts a date-time time.Time to string. +func TimeToString(value time.Time) string { + return value.Format(time.RFC3339Nano) +} + +// Converts a date-time *time.Time to *string. +func TimePointerToStringPointer(value *time.Time) *string { + if value == nil { + return nil + } + + stringValue := TimeToString(*value) + + return &stringValue +} diff --git a/internal/provider/typeconvert/int32.go b/internal/provider/typeconvert/int32.go new file mode 100644 index 0000000..9b4f3f9 --- /dev/null +++ b/internal/provider/typeconvert/int32.go @@ -0,0 +1,14 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package typeconvert + +// Converts an *int to *int32. +func IntPointerToInt32Pointer(value *int) *int32 { + if value == nil { + return nil + } + + int32Value := int32(*value) + + return &int32Value +} diff --git a/internal/provider/types/base_entity_acl.go b/internal/provider/types/base_entity_acl.go deleted file mode 100644 index ea0f5f9..0000000 --- a/internal/provider/types/base_entity_acl.go +++ /dev/null @@ -1,11 +0,0 @@ -// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. - -package types - -import "github.com/hashicorp/terraform-plugin-framework/types" - -type BaseEntityACL struct { - Delete []types.String `tfsdk:"delete"` - Edit []types.String `tfsdk:"edit"` - View []types.String `tfsdk:"view"` -} diff --git a/internal/provider/types/base_entity_owner.go b/internal/provider/types/base_entity_owner.go deleted file mode 100644 index 10d217d..0000000 --- a/internal/provider/types/base_entity_owner.go +++ /dev/null @@ -1,10 +0,0 @@ -// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. - -package types - -import "github.com/hashicorp/terraform-plugin-framework/types" - -type BaseEntityOwner struct { - OrgID types.String `tfsdk:"org_id"` - UserID types.String `tfsdk:"user_id"` -} diff --git a/internal/provider/types/file_item.go b/internal/provider/types/file_item.go deleted file mode 100644 index 510bf6d..0000000 --- a/internal/provider/types/file_item.go +++ /dev/null @@ -1,13 +0,0 @@ -// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. - -package types - -import "github.com/hashicorp/terraform-plugin-framework/types" - -type FileItem struct { - Filename types.String `tfsdk:"filename"` - MimeType types.String `tfsdk:"mime_type"` - ReadableSize types.String `tfsdk:"readable_size"` - S3ref *S3Ref `tfsdk:"s3ref"` - SizeBytes types.Int64 `tfsdk:"size_bytes"` -} diff --git a/internal/provider/types/s3_ref.go b/internal/provider/types/s3_ref.go deleted file mode 100644 index e270ebd..0000000 --- a/internal/provider/types/s3_ref.go +++ /dev/null @@ -1,10 +0,0 @@ -// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. - -package types - -import "github.com/hashicorp/terraform-plugin-framework/types" - -type S3Ref struct { - Bucket types.String `tfsdk:"bucket"` - Key types.String `tfsdk:"key"` -} diff --git a/internal/provider/utils.go b/internal/provider/utils.go index 7086c77..349d389 100644 --- a/internal/provider/utils.go +++ b/internal/provider/utils.go @@ -3,17 +3,25 @@ package provider import ( + "bufio" + "bytes" "context" - "encoding/json" + "errors" "fmt" - tfReflect "github.com/epilot-dev/terraform-provider-epilot-file/internal/provider/reflect" + "io" + "net/http" + "net/http/httputil" + "net/textproto" + "strings" + + "github.com/hashicorp/go-uuid" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/types" - "net/http" - "net/http/httputil" - "reflect" + "github.com/hashicorp/terraform-plugin-log/tflog" + + tfReflect "github.com/epilot-dev/terraform-provider-epilot-file/internal/provider/reflect" ) func debugResponse(response *http.Response) string { @@ -40,19 +48,6 @@ func debugResponse(response *http.Response) string { return fmt.Sprintf("**Request**:\n%s\n**Response**:\n%s", string(dumpReq), string(dumpRes)) } -func reflectJSONKey(data any, key string) reflect.Value { - jsonIfied, err := json.Marshal(data) - if err != nil { - panic(fmt.Errorf("failed to marshal data: %w", err)) - } - var jsonMap map[string]interface{} - err = json.Unmarshal(jsonIfied, &jsonMap) - if err != nil { - panic(fmt.Errorf("failed to unmarshal data: %w", err)) - } - return reflect.ValueOf(jsonMap[key]) -} - func merge(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse, target interface{}) { var plan types.Object var state types.Object @@ -78,19 +73,228 @@ func merge(ctx context.Context, req resource.UpdateRequest, resp *resource.Updat return } - refreshPlan(ctx, plan, target, resp.Diagnostics) + resp.Diagnostics.Append(refreshPlan(ctx, plan, target)...) } -func refreshPlan(ctx context.Context, plan types.Object, target interface{}, diagnostics diag.Diagnostics) { +func refreshPlan(ctx context.Context, plan types.Object, target any) diag.Diagnostics { + var diags diag.Diagnostics + obj := types.ObjectType{AttrTypes: plan.AttributeTypes(ctx)} val, err := plan.ToTerraformValue(ctx) if err != nil { - diagnostics.Append(diag.NewErrorDiagnostic("Object Conversion Error", "An unexpected error was encountered trying to convert object. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error())) - return + diags.AddError( + "Object Conversion Error", + "An unexpected error was encountered trying to convert object. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(), + ) + return diags } - diagnostics.Append(tfReflect.Into(ctx, obj, val, target, tfReflect.Options{ + + diags.Append(tfReflect.Into(ctx, obj, val, target, tfReflect.Options{ UnhandledNullAsEmpty: true, UnhandledUnknownAsEmpty: true, SourceType: tfReflect.SourceTypePlan, }, path.Empty())...) + + return diags +} + +// Configurable options for the provider HTTP transport. +type ProviderHTTPTransportOpts struct { + // HTTP headers to set on all requests. + SetHeaders map[string]string + + // Underlying HTTP transport. + Transport http.RoundTripper +} + +// Note: this is taken as a more minimal/specific version of https://github.com/hashicorp/terraform-plugin-sdk/blob/main/helper/logging/logging_http_transport.go +func NewProviderHTTPTransport(opts ProviderHTTPTransportOpts) *providerHttpTransport { + return &providerHttpTransport{ + setHeaders: opts.SetHeaders, + transport: opts.Transport, + } +} + +const ( + FieldHttpOperationType = "tf_http_op_type" + OperationHttpRequest = "request" + OperationHttpResponse = "response" + FieldHttpRequestMethod = "tf_http_req_method" + FieldHttpRequestUri = "tf_http_req_uri" + FieldHttpRequestProtoVersion = "tf_http_req_version" + FieldHttpRequestBody = "tf_http_req_body" + FieldHttpResponseProtoVersion = "tf_http_res_version" + FieldHttpResponseStatusCode = "tf_http_res_status_code" + FieldHttpResponseStatusReason = "tf_http_res_status_reason" + FieldHttpResponseBody = "tf_http_res_body" + FieldHttpTransactionId = "tf_http_trans_id" +) + +type providerHttpTransport struct { + setHeaders map[string]string + transport http.RoundTripper +} + +func (t *providerHttpTransport) RoundTrip(req *http.Request) (*http.Response, error) { + ctx := req.Context() + ctx = t.addTransactionIdField(ctx) + + // Set globally defined HTTP headers in the request + t.setRequestHeaders(req) + + // Decompose the request bytes in a message (HTTP body) and fields (HTTP headers), then log it + fields, err := decomposeRequestForLogging(req) + if err != nil { + tflog.Error(ctx, "Failed to parse request bytes for logging", []map[string]interface{}{map[string]interface{}{ + "error": err, + }}...) + } else { + tflog.Debug(ctx, "Sending HTTP Request", []map[string]interface{}{fields}...) + } + + // Invoke the wrapped RoundTrip now + res, err := t.transport.RoundTrip(req) + if err != nil { + return res, err + } + + // Decompose the response bytes in a message (HTTP body) and fields (HTTP headers), then log it + fields, err = decomposeResponseForLogging(res) + if err != nil { + tflog.Error(ctx, "Failed to parse response bytes for logging", []map[string]interface{}{map[string]interface{}{ + "error": err, + }}...) + } else { + tflog.Debug(ctx, "Received HTTP Response", []map[string]interface{}{fields}...) + } + + return res, nil +} + +// Generates UUID and sets it into the tf_http_trans_id logging field. +func (t *providerHttpTransport) addTransactionIdField(ctx context.Context) context.Context { + tId, err := uuid.GenerateUUID() + + if err != nil { + tId = "Unable to assign Transaction ID: " + err.Error() + } + + return tflog.SetField(ctx, FieldHttpTransactionId, tId) +} + +// Sets globally defined HTTP headers in the request. +func (t *providerHttpTransport) setRequestHeaders(req *http.Request) { + for name, value := range t.setHeaders { + req.Header.Set(name, value) + } +} + +func decomposeRequestForLogging(req *http.Request) (map[string]interface{}, error) { + fields := make(map[string]interface{}, len(req.Header)+4) + fields[FieldHttpOperationType] = OperationHttpRequest + + fields[FieldHttpRequestMethod] = req.Method + fields[FieldHttpRequestUri] = req.URL.RequestURI() + fields[FieldHttpRequestProtoVersion] = req.Proto + + // Get the full body of the request, including headers appended by http.Transport: + // this is necessary because the http.Request at this stage doesn't contain + // all the headers that will be eventually sent. + // We rely on `httputil.DumpRequestOut` to obtain the actual bytes that will be sent out. + reqBytes, err := httputil.DumpRequestOut(req, true) + if err != nil { + return nil, err + } + + // Create a reader around the request full body + reqReader := textproto.NewReader(bufio.NewReader(bytes.NewReader(reqBytes))) + + err = fieldHeadersFromRequestReader(reqReader, fields) + if err != nil { + return nil, err + } + + // Read the rest of the body content + fields[FieldHttpRequestBody] = bodyFromRestOfRequestReader(reqReader) + return fields, nil +} + +func fieldHeadersFromRequestReader(reader *textproto.Reader, fields map[string]interface{}) error { + // Ignore the first line: it contains non-header content + // that we have already captured. + // Skipping this step, would cause the following call to `ReadMIMEHeader()` + // to fail as it cannot parse the first line. + _, err := reader.ReadLine() + if err != nil { + return err + } + + // Read the MIME-style headers + mimeHeader, err := reader.ReadMIMEHeader() + if err != nil { + return err + } + + // Set the headers as fields to log + for k, v := range mimeHeader { + if len(v) == 1 { + fields[k] = v[0] + } else { + fields[k] = v + } + } + if _, ok := fields["Authorization"]; ok { + fields["Authorization"] = "(sensitive)" + } + if _, ok := fields["token"]; ok { + fields["token"] = "(sensitive)" + } + + return nil +} + +func bodyFromRestOfRequestReader(reader *textproto.Reader) string { + var builder strings.Builder + for { + line, err := reader.ReadContinuedLine() + if errors.Is(err, io.EOF) { + break + } + builder.WriteString(line) + } + + return builder.String() +} + +func decomposeResponseForLogging(res *http.Response) (map[string]interface{}, error) { + fields := make(map[string]interface{}, len(res.Header)+4) + fields[FieldHttpOperationType] = OperationHttpResponse + + fields[FieldHttpResponseProtoVersion] = res.Proto + fields[FieldHttpResponseStatusCode] = res.StatusCode + fields[FieldHttpResponseStatusReason] = res.Status + + // Set the headers as fields to log + for k, v := range res.Header { + if len(v) == 1 { + fields[k] = v[0] + } else { + fields[k] = v + } + } + + // Read the whole response body + resBody, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + // Wrap the bytes from the response body, back into an io.ReadCloser, + // to respect the interface of http.Response, as expected by users of the + // http.Client + res.Body = io.NopCloser(bytes.NewBuffer(resBody)) + + fields[FieldHttpResponseBody] = string(resBody) + + return fields, nil } diff --git a/internal/sdk/.gitignore b/internal/sdk/.gitignore index d3c2f59..9de5d38 100644 --- a/internal/sdk/.gitignore +++ b/internal/sdk/.gitignore @@ -1 +1,3 @@ +.speakeasy/temp/ +.speakeasy/reports # .gitignore diff --git a/internal/sdk/deprecated.go b/internal/sdk/deprecated.go index 78cad8d..b52975c 100644 --- a/internal/sdk/deprecated.go +++ b/internal/sdk/deprecated.go @@ -6,13 +6,11 @@ import ( "bytes" "context" "fmt" - "github.com/cenkalti/backoff/v4" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/hooks" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/utils" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/errors" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/operations" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/shared" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/retry" "net/http" "net/url" ) @@ -35,18 +33,10 @@ func newDeprecated(sdkConfig sdkConfiguration) *Deprecated { // // # Saves metadata to file entity // -// Deprecated method: This will be removed in a future release, please migrate away from it as soon as possible. +// Deprecated: This will be removed in a future release, please migrate away from it as soon as possible. func (s *Deprecated) SaveFile(ctx context.Context, request operations.SaveFileRequest, opts ...operations.Option) (*operations.SaveFileResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "saveFile", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -56,12 +46,24 @@ func (s *Deprecated) SaveFile(ctx context.Context, request operations.SaveFileRe } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v1/files") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "saveFile", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, true, "SaveFilePayload", "json", `request:"mediaType=application/json"`) if err != nil { return nil, err @@ -84,7 +86,9 @@ func (s *Deprecated) SaveFile(ctx context.Context, request operations.SaveFileRe } req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) - req.Header.Set("Content-Type", reqContentType) + if reqContentType != "" { + req.Header.Set("Content-Type", reqContentType) + } if err := utils.PopulateQueryParams(ctx, req, request, nil); err != nil { return nil, fmt.Errorf("error populating query params: %w", err) @@ -94,94 +98,36 @@ func (s *Deprecated) SaveFile(ctx context.Context, request operations.SaveFileRe return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -230,18 +176,10 @@ func (s *Deprecated) SaveFile(ctx context.Context, request operations.SaveFileRe // // Use the saveFile operation to store file file permanently. // -// Deprecated method: This will be removed in a future release, please migrate away from it as soon as possible. +// Deprecated: This will be removed in a future release, please migrate away from it as soon as possible. func (s *Deprecated) UploadFile(ctx context.Context, request operations.UploadFileRequest, opts ...operations.Option) (*operations.UploadFileResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "uploadFile", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -251,12 +189,24 @@ func (s *Deprecated) UploadFile(ctx context.Context, request operations.UploadFi } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v1/files/upload") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "uploadFile", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, true, "UploadFilePayload", "json", `request:"mediaType=application/json"`) if err != nil { return nil, err @@ -279,7 +229,9 @@ func (s *Deprecated) UploadFile(ctx context.Context, request operations.UploadFi } req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) - req.Header.Set("Content-Type", reqContentType) + if reqContentType != "" { + req.Header.Set("Content-Type", reqContentType) + } if err := utils.PopulateQueryParams(ctx, req, request, nil); err != nil { return nil, fmt.Errorf("error populating query params: %w", err) @@ -289,94 +241,36 @@ func (s *Deprecated) UploadFile(ctx context.Context, request operations.UploadFi return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } diff --git a/internal/sdk/file.go b/internal/sdk/file.go index 1ddc161..dcd17c8 100644 --- a/internal/sdk/file.go +++ b/internal/sdk/file.go @@ -6,13 +6,11 @@ import ( "bytes" "context" "fmt" - "github.com/cenkalti/backoff/v4" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/hooks" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/utils" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/errors" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/operations" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/shared" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/retry" "net/http" "net/url" ) @@ -31,16 +29,8 @@ func newFile(sdkConfig sdkConfiguration) *File { // DeleteFile - deleteFile // Delete a file entity by id func (s *File) DeleteFile(ctx context.Context, request operations.DeleteFileRequest, opts ...operations.Option) (*operations.DeleteFileResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "deleteFile", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -50,12 +40,25 @@ func (s *File) DeleteFile(ctx context.Context, request operations.DeleteFileRequ } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := utils.GenerateURL(ctx, baseURL, "/v2/files/{id}", request, nil) if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "deleteFile", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -82,94 +85,36 @@ func (s *File) DeleteFile(ctx context.Context, request operations.DeleteFileRequ return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -216,16 +161,8 @@ func (s *File) DeleteFile(ctx context.Context, request operations.DeleteFileRequ // DownloadFile - downloadFile // Generate pre-signed download S3 url for a file func (s *File) DownloadFile(ctx context.Context, request operations.DownloadFileRequest, opts ...operations.Option) (*operations.DownloadFileResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "downloadFile", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -235,12 +172,25 @@ func (s *File) DownloadFile(ctx context.Context, request operations.DownloadFile } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := utils.GenerateURL(ctx, baseURL, "/v1/files/{id}/download", request, nil) if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "downloadFile", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -267,94 +217,36 @@ func (s *File) DownloadFile(ctx context.Context, request operations.DownloadFile return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -401,16 +293,8 @@ func (s *File) DownloadFile(ctx context.Context, request operations.DownloadFile // DownloadFiles - downloadFiles // Bulk generate pre-signed download S3 urls for multiple files func (s *File) DownloadFiles(ctx context.Context, request []shared.DownloadFilesPayload, opts ...operations.Option) (*operations.DownloadFilesResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "downloadFiles", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -420,12 +304,24 @@ func (s *File) DownloadFiles(ctx context.Context, request []shared.DownloadFiles } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v1/files:downloadFiles") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "downloadFiles", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, true, "Request", "json", `request:"mediaType=application/json"`) if err != nil { return nil, err @@ -448,100 +344,44 @@ func (s *File) DownloadFiles(ctx context.Context, request []shared.DownloadFiles } req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) - req.Header.Set("Content-Type", reqContentType) + if reqContentType != "" { + req.Header.Set("Content-Type", reqContentType) + } if err := utils.PopulateSecurity(ctx, req, s.sdkConfiguration.Security); err != nil { return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -588,16 +428,8 @@ func (s *File) DownloadFiles(ctx context.Context, request []shared.DownloadFiles // DownloadS3File - downloadS3File // Generate pre-signed download S3 url for a file func (s *File) DownloadS3File(ctx context.Context, request operations.DownloadS3FileRequest, opts ...operations.Option) (*operations.DownloadS3FileResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "downloadS3File", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -607,12 +439,25 @@ func (s *File) DownloadS3File(ctx context.Context, request operations.DownloadS3 } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v1/files:downloadS3") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "downloadS3File", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -639,95 +484,37 @@ func (s *File) DownloadS3File(ctx context.Context, request operations.DownloadS3 return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { + if err != nil { + err = fmt.Errorf("error sending request: %w", err) + } else { + err = fmt.Errorf("error sending request: no response") + } + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + } else if _httpRes != nil { + httpRes = _httpRes } } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) if err != nil { return nil, err } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } - } } res := &operations.DownloadS3FileResponse{ @@ -773,16 +560,8 @@ func (s *File) DownloadS3File(ctx context.Context, request operations.DownloadS3 // GetFile - getFile // Get a file entity by id func (s *File) GetFile(ctx context.Context, request operations.GetFileRequest, opts ...operations.Option) (*operations.GetFileResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "getFile", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -792,12 +571,25 @@ func (s *File) GetFile(ctx context.Context, request operations.GetFileRequest, o } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := utils.GenerateURL(ctx, baseURL, "/v2/files/{id}", request, nil) if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "getFile", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -824,94 +616,36 @@ func (s *File) GetFile(ctx context.Context, request operations.GetFileRequest, o return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -960,16 +694,8 @@ func (s *File) GetFile(ctx context.Context, request operations.GetFileRequest, o // // Saves metadata to file entity and stores a version when `s3ref` or `source_url` is passed. func (s *File) SaveFileV2(ctx context.Context, request operations.SaveFileV2Request, opts ...operations.Option) (*operations.SaveFileV2Response, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "saveFileV2", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -979,12 +705,24 @@ func (s *File) SaveFileV2(ctx context.Context, request operations.SaveFileV2Requ } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v2/files") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "saveFileV2", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, true, "SaveFilePayloadV2", "json", `request:"mediaType=application/json"`) if err != nil { return nil, err @@ -1007,7 +745,9 @@ func (s *File) SaveFileV2(ctx context.Context, request operations.SaveFileV2Requ } req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) - req.Header.Set("Content-Type", reqContentType) + if reqContentType != "" { + req.Header.Set("Content-Type", reqContentType) + } if err := utils.PopulateQueryParams(ctx, req, request, nil); err != nil { return nil, fmt.Errorf("error populating query params: %w", err) @@ -1017,94 +757,36 @@ func (s *File) SaveFileV2(ctx context.Context, request operations.SaveFileV2Requ return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -1153,16 +835,8 @@ func (s *File) SaveFileV2(ctx context.Context, request operations.SaveFileV2Requ // // Use the saveFileV2 operation to store file file permanently. func (s *File) UploadFilePublic(ctx context.Context, request *shared.UploadFilePayload, opts ...operations.Option) (*operations.UploadFilePublicResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "uploadFilePublic", - OAuth2Scopes: []string{}, - SecuritySource: nil, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -1172,12 +846,24 @@ func (s *File) UploadFilePublic(ctx context.Context, request *shared.UploadFileP } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v1/files/public/upload") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "uploadFilePublic", + OAuth2Scopes: []string{}, + SecuritySource: nil, + } bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, true, "Request", "json", `request:"mediaType=application/json"`) if err != nil { return nil, err @@ -1200,96 +886,40 @@ func (s *File) UploadFilePublic(ctx context.Context, request *shared.UploadFileP } req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) - req.Header.Set("Content-Type", reqContentType) - - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + if reqContentType != "" { + req.Header.Set("Content-Type", reqContentType) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) + } - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -1338,16 +968,8 @@ func (s *File) UploadFilePublic(ctx context.Context, request *shared.UploadFileP // // Use the saveFileV2 operation to store file file permanently. func (s *File) UploadFileV2(ctx context.Context, request operations.UploadFileV2Request, opts ...operations.Option) (*operations.UploadFileV2Response, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "uploadFileV2", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -1357,12 +979,24 @@ func (s *File) UploadFileV2(ctx context.Context, request operations.UploadFileV2 } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v2/files/upload") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "uploadFileV2", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, true, "UploadFilePayload", "json", `request:"mediaType=application/json"`) if err != nil { return nil, err @@ -1385,7 +1019,9 @@ func (s *File) UploadFileV2(ctx context.Context, request operations.UploadFileV2 } req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) - req.Header.Set("Content-Type", reqContentType) + if reqContentType != "" { + req.Header.Set("Content-Type", reqContentType) + } if err := utils.PopulateQueryParams(ctx, req, request, nil); err != nil { return nil, fmt.Errorf("error populating query params: %w", err) @@ -1395,94 +1031,36 @@ func (s *File) UploadFileV2(ctx context.Context, request operations.UploadFileV2 return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -1529,16 +1107,8 @@ func (s *File) UploadFileV2(ctx context.Context, request operations.UploadFileV2 // VerifyCustomDownloadURL - verifyCustomDownloadUrl // Verify a pre-signed custom download url for a file func (s *File) VerifyCustomDownloadURL(ctx context.Context, request *shared.VerifyCustomDownloadURLPayload, opts ...operations.Option) (*operations.VerifyCustomDownloadURLResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "verifyCustomDownloadUrl", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -1548,12 +1118,24 @@ func (s *File) VerifyCustomDownloadURL(ctx context.Context, request *shared.Veri } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v1/files/download:verify") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "verifyCustomDownloadUrl", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, true, "Request", "json", `request:"mediaType=application/json"`) if err != nil { return nil, err @@ -1576,100 +1158,44 @@ func (s *File) VerifyCustomDownloadURL(ctx context.Context, request *shared.Veri } req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) - req.Header.Set("Content-Type", reqContentType) + if reqContentType != "" { + req.Header.Set("Content-Type", reqContentType) + } if err := utils.PopulateSecurity(ctx, req, s.sdkConfiguration.Security); err != nil { return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } diff --git a/internal/sdk/internal/hooks/hooks.go b/internal/sdk/internal/hooks/hooks.go index 8ea491a..a0b49da 100644 --- a/internal/sdk/internal/hooks/hooks.go +++ b/internal/sdk/internal/hooks/hooks.go @@ -24,6 +24,7 @@ type HTTPClient interface { } type HookContext struct { + BaseURL string Context context.Context OperationID string OAuth2Scopes []string diff --git a/internal/sdk/internal/utils/env.go b/internal/sdk/internal/utils/env.go new file mode 100644 index 0000000..110d464 --- /dev/null +++ b/internal/sdk/internal/utils/env.go @@ -0,0 +1,16 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package utils + +import ( + "os" +) + +// GetEnv returns the value of the environment variable named by the key or the defaultValue if the environment variable is not set. +func GetEnv(name, defaultValue string) string { + value := os.Getenv(name) + if value == "" { + return defaultValue + } + return value +} diff --git a/internal/sdk/internal/utils/form.go b/internal/sdk/internal/utils/form.go index 387a62a..95e9a71 100644 --- a/internal/sdk/internal/utils/form.go +++ b/internal/sdk/internal/utils/form.go @@ -15,11 +15,15 @@ import ( "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/types" ) -func populateForm(paramName string, explode bool, objType reflect.Type, objValue reflect.Value, delimiter string, getFieldName func(reflect.StructField) string) url.Values { +func populateForm(paramName string, explode bool, objType reflect.Type, objValue reflect.Value, delimiter string, defaultValue *string, getFieldName func(reflect.StructField) string) url.Values { formValues := url.Values{} if isNil(objType, objValue) { + if defaultValue != nil { + formValues.Add(paramName, *defaultValue) + } + return formValues } diff --git a/internal/sdk/internal/utils/json.go b/internal/sdk/internal/utils/json.go index c67ba9b..bf94619 100644 --- a/internal/sdk/internal/utils/json.go +++ b/internal/sdk/internal/utils/json.go @@ -186,8 +186,8 @@ func UnmarshalJSON(b []byte, v interface{}, tag reflect.StructTag, topLevel bool value, ok := unmarhsaled[fieldName] if !ok { - defaultTag := field.Tag.Get("default") - if defaultTag != "" { + defaultTag, defaultOk := field.Tag.Lookup("default") + if defaultOk { value = handleDefaultConstValue(defaultTag, fieldVal.Interface(), field.Tag) ok = true } @@ -257,8 +257,8 @@ func marshalValue(v interface{}, tag reflect.StructTag) (json.RawMessage, error) } if isNil(reflect.TypeOf(v), reflect.ValueOf(v)) { - defaultTag := tag.Get("default") - if defaultTag != "" { + defaultTag, ok := tag.Lookup("default") + if ok { return handleDefaultConstValue(defaultTag, v, tag), nil } diff --git a/internal/sdk/internal/utils/queryparams.go b/internal/sdk/internal/utils/queryparams.go index 8b33231..d7d3b11 100644 --- a/internal/sdk/internal/utils/queryparams.go +++ b/internal/sdk/internal/utils/queryparams.go @@ -65,6 +65,14 @@ func populateQueryParams(queryParams interface{}, globals interface{}, values ur continue } + constValue := parseConstTag(fieldType) + if constValue != nil { + values.Add(qpTag.ParamName, *constValue) + continue + } + + defaultValue := parseDefaultTag(fieldType) + if globals != nil { var globalFound bool fieldType, valType, globalFound = populateFromGlobals(fieldType, valType, queryParamTagKey, globals) @@ -91,14 +99,14 @@ func populateQueryParams(queryParams interface{}, globals interface{}, values ur } } case "form": - vals := populateFormParams(qpTag, fieldType.Type, valType, ",") + vals := populateFormParams(qpTag, fieldType.Type, valType, ",", defaultValue) for k, v := range vals { for _, vv := range v { values.Add(k, vv) } } case "pipeDelimited": - vals := populateFormParams(qpTag, fieldType.Type, valType, "|") + vals := populateFormParams(qpTag, fieldType.Type, valType, "|", defaultValue) for k, v := range vals { for _, vv := range v { values.Add(k, vv) @@ -214,7 +222,11 @@ func populateDeepObjectParamsStruct(qsValues url.Values, priorScope string, stru continue } - scope := priorScope + "[" + qpTag.ParamName + "]" + scope := priorScope + + if !qpTag.Inline { + scope = priorScope + "[" + qpTag.ParamName + "]" + } switch fieldValue.Kind() { case reflect.Array, reflect.Slice: @@ -236,8 +248,8 @@ func populateDeepObjectParamsStruct(qsValues url.Values, priorScope string, stru } } -func populateFormParams(tag *paramTag, objType reflect.Type, objValue reflect.Value, delimiter string) url.Values { - return populateForm(tag.ParamName, tag.Explode, objType, objValue, delimiter, func(fieldType reflect.StructField) string { +func populateFormParams(tag *paramTag, objType reflect.Type, objValue reflect.Value, delimiter string, defaultValue *string) url.Values { + return populateForm(tag.ParamName, tag.Explode, objType, objValue, delimiter, defaultValue, func(fieldType reflect.StructField) string { qpTag := parseQueryParamTag(fieldType) if qpTag == nil { return "" @@ -252,6 +264,13 @@ type paramTag struct { Explode bool ParamName string Serialization string + + // Inline is a special case for union/oneOf. When a wrapper struct type is + // used, each union/oneOf value field should be inlined (e.g. not appended + // in deepObject style with the name) as if the value was directly on the + // parent struct field. Without this annotation, the value would not be + // encoded by downstream logic that requires the struct field tag. + Inline bool } func parseQueryParamTag(field reflect.StructField) *paramTag { diff --git a/internal/sdk/internal/utils/requestbody.go b/internal/sdk/internal/utils/requestbody.go index 000226e..8fe01ad 100644 --- a/internal/sdk/internal/utils/requestbody.go +++ b/internal/sdk/internal/utils/requestbody.go @@ -166,7 +166,7 @@ func encodeMultipartFormData(w io.Writer, data interface{}) (string, error) { tag := parseMultipartFormTag(field) if tag.File { - if err := encodeMultipartFormDataFile(writer, fieldType, valType); err != nil { + if err := encodeMultipartFormDataFile(writer, tag.Name, fieldType, valType); err != nil { writer.Close() return "", err } @@ -211,12 +211,11 @@ func encodeMultipartFormData(w io.Writer, data interface{}) (string, error) { return writer.FormDataContentType(), nil } -func encodeMultipartFormDataFile(w *multipart.Writer, fieldType reflect.Type, valType reflect.Value) error { +func encodeMultipartFormDataFile(w *multipart.Writer, fieldName string, fieldType reflect.Type, valType reflect.Value) error { if fieldType.Kind() != reflect.Struct { return fmt.Errorf("invalid type %s for multipart/form-data file", valType.Type()) } - var fieldName string var fileName string var reader io.Reader @@ -236,12 +235,11 @@ func encodeMultipartFormDataFile(w *multipart.Writer, fieldType reflect.Type, va reader = val.Interface().(io.Reader) } } else { - fieldName = tag.Name fileName = val.String() } } - if fieldName == "" || fileName == "" || reader == nil { + if fileName == "" || reader == nil { return fmt.Errorf("invalid multipart/form-data file") } @@ -294,7 +292,7 @@ func encodeFormData(fieldName string, w io.Writer, data interface{}) error { switch tag.Style { // TODO: support other styles case "form": - values := populateForm(tag.Name, tag.Explode, fieldType, valType, ",", func(sf reflect.StructField) string { + values := populateForm(tag.Name, tag.Explode, fieldType, valType, ",", nil, func(sf reflect.StructField) string { tag := parseFormTag(field) if tag == nil { return "" diff --git a/internal/sdk/internal/utils/retries.go b/internal/sdk/internal/utils/retries.go index 72d43ba..3e00c58 100644 --- a/internal/sdk/internal/utils/retries.go +++ b/internal/sdk/internal/utils/retries.go @@ -6,8 +6,9 @@ import ( "context" "errors" "fmt" - "github.com/cenkalti/backoff/v4" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/retry" + "math" + "math/rand" "net/http" "net/url" "strconv" @@ -15,8 +16,6 @@ import ( "time" ) -var errRequestFailed = errors.New("request failed") - // Deprecated: Use retry.BackoffStrategy instead. type BackoffStrategy = retry.BackoffStrategy @@ -28,34 +27,27 @@ type Retries struct { StatusCodes []string } -func Retry(ctx context.Context, r Retries, action func() (*http.Response, error)) (*http.Response, error) { +func Retry(ctx context.Context, r Retries, operation func() (*http.Response, error)) (*http.Response, error) { switch r.Config.Strategy { case "backoff": if r.Config.Backoff == nil { - return action() + return operation() } - config := backoff.NewExponentialBackOff() - config.InitialInterval = time.Duration(r.Config.Backoff.InitialInterval) * time.Millisecond - config.MaxInterval = time.Duration(r.Config.Backoff.MaxInterval) * time.Millisecond - config.Multiplier = r.Config.Backoff.Exponent - config.MaxElapsedTime = time.Duration(r.Config.Backoff.MaxElapsedTime) * time.Millisecond - config.Reset() - var resp *http.Response - err := backoff.Retry(func() error { + err := retryWithBackoff(ctx, r.Config.Backoff, func() error { if resp != nil { resp.Body.Close() } select { case <-ctx.Done(): - return backoff.Permanent(ctx.Err()) + return retry.Permanent(ctx.Err()) default: } - res, err := action() + res, err := operation() if err != nil { urlError := new(url.Error) if errors.As(err, &urlError) { @@ -64,7 +56,7 @@ func Retry(ctx context.Context, r Retries, action func() (*http.Response, error) } } - return backoff.Permanent(err) + return retry.Permanent(err) } resp = res if res == nil { @@ -81,7 +73,7 @@ func Retry(ctx context.Context, r Retries, action func() (*http.Response, error) s := res.StatusCode / 100 if s >= codeRange && s < codeRange+1 { - return errRequestFailed + return retry.TemporaryFromResponse("request failed", res) } } else { parsedCode, err := strconv.Atoi(code) @@ -90,7 +82,7 @@ func Retry(ctx context.Context, r Retries, action func() (*http.Response, error) } if res.StatusCode == parsedCode { - return errRequestFailed + return retry.TemporaryFromResponse("request failed", res) } } } @@ -98,13 +90,131 @@ func Retry(ctx context.Context, r Retries, action func() (*http.Response, error) resp = res return nil - }, config) - if err != nil && !errors.Is(err, errRequestFailed) { + }) + + var tempErr *retry.TemporaryError + if err != nil && !errors.As(err, &tempErr) { return nil, err } return resp, nil default: - return action() + return operation() + } +} + +func retryWithBackoff(ctx context.Context, s *retry.BackoffStrategy, operation func() error) error { + var ( + err error + next time.Duration + attempt int + start = time.Now() + maxElapsedTime = time.Duration(s.MaxElapsedTime) * time.Millisecond + ) + + timer := &defaultTimer{} + defer func() { + timer.Stop() + }() + + for { + err = operation() + if err == nil { + return nil + } + + var permanent *retry.PermanentError + if errors.As(err, &permanent) { + return permanent.Unwrap() + } + + if time.Since(start) >= maxElapsedTime { + return err + } + + var temporary *retry.TemporaryError + if errors.As(err, &temporary) { + next = temporary.RetryAfter() + } + + if next <= 0 { + next = nextInterval(s, attempt) + } + + timer.Start(next) + + select { + case <-ctx.Done(): + return ctx.Err() + case <-timer.C(): + } + + attempt += 1 } } + +type Timer interface { + Start(duration time.Duration) + Stop() + C() <-chan time.Time +} + +// defaultTimer implements Timer interface using time.Timer +type defaultTimer struct { + timer *time.Timer +} + +// C returns the timers channel which receives the current time when the timer fires. +func (t *defaultTimer) C() <-chan time.Time { + return t.timer.C +} + +// Start starts the timer to fire after the given duration +func (t *defaultTimer) Start(duration time.Duration) { + if t.timer == nil { + t.timer = time.NewTimer(duration) + return + } + + if !t.timer.Stop() { + select { + case <-t.timer.C: + default: + } + } + + t.timer.Reset(duration) +} + +// Stop is called when the timer is not used anymore and resources may be freed. +func (t *defaultTimer) Stop() { + if t.timer != nil { + t.timer.Stop() + } +} + +func nextInterval(s *retry.BackoffStrategy, attempt int) time.Duration { + initialInterval := float64(time.Duration(s.InitialInterval) * time.Millisecond) + maxInterval := float64(time.Duration(s.MaxInterval) * time.Millisecond) + exponent := s.Exponent + jitterFactor := float64(0.25) + + interval := initialInterval * math.Pow(float64(attempt+1), exponent) + + jitter := rand.Float64() * jitterFactor * interval + if rand.Float64() < 0.5 { + jitter = -1 * jitter + } + + interval = interval + jitter + + if interval <= 0 { + interval = initialInterval + } + + if interval > maxInterval { + interval = maxInterval + } + + return time.Duration(interval) +} diff --git a/internal/sdk/internal/utils/utils.go b/internal/sdk/internal/utils/utils.go index f1ff9e0..6f1f538 100644 --- a/internal/sdk/internal/utils/utils.go +++ b/internal/sdk/internal/utils/utils.go @@ -96,6 +96,26 @@ func AsSecuritySource(security interface{}) func(context.Context) (interface{}, } } +func parseConstTag(field reflect.StructField) *string { + value := field.Tag.Get("const") + + if value == "" { + return nil + } + + return &value +} + +func parseDefaultTag(field reflect.StructField) *string { + value := field.Tag.Get("default") + + if value == "" { + return nil + } + + return &value +} + func parseStructTag(tagKey string, field reflect.StructField) map[string]string { tag := field.Tag.Get(tagKey) if tag == "" { @@ -127,6 +147,7 @@ func parseStructTag(tagKey string, field reflect.StructField) map[string]string func parseParamTag(tagKey string, field reflect.StructField, defaultStyle string, defaultExplode bool) *paramTag { // example `{tagKey}:"style=simple,explode=false,name=apiID"` + // example `{tagKey}:"inline"` values := parseStructTag(tagKey, field) if values == nil { return nil @@ -140,6 +161,8 @@ func parseParamTag(tagKey string, field reflect.StructField, defaultStyle string for k, v := range values { switch k { + case "inline": + tag.Inline = v == "true" case "style": tag.Style = v case "explode": diff --git a/internal/sdk/models/operations/accesspubliclink.go b/internal/sdk/models/operations/accesspubliclink.go index 6bd8927..217c945 100644 --- a/internal/sdk/models/operations/accesspubliclink.go +++ b/internal/sdk/models/operations/accesspubliclink.go @@ -7,8 +7,9 @@ import ( ) type AccessPublicLinkRequest struct { - Filename string `pathParam:"style=simple,explode=false,name=filename"` - ID string `pathParam:"style=simple,explode=false,name=id"` + Filename string `pathParam:"style=simple,explode=false,name=filename"` + Hash *string `queryParam:"style=form,explode=true,name=hash"` + ID string `pathParam:"style=simple,explode=false,name=id"` } func (o *AccessPublicLinkRequest) GetFilename() string { @@ -18,6 +19,13 @@ func (o *AccessPublicLinkRequest) GetFilename() string { return o.Filename } +func (o *AccessPublicLinkRequest) GetHash() *string { + if o == nil { + return nil + } + return o.Hash +} + func (o *AccessPublicLinkRequest) GetID() string { if o == nil { return "" diff --git a/internal/sdk/models/operations/getfile.go b/internal/sdk/models/operations/getfile.go index 6e74cfc..1579f1f 100644 --- a/internal/sdk/models/operations/getfile.go +++ b/internal/sdk/models/operations/getfile.go @@ -10,8 +10,9 @@ import ( type GetFileRequest struct { // Don't wait for updated entity to become available in Search API. Useful for large migrations - Async *bool `default:"false" queryParam:"style=form,explode=true,name=async"` - ID string `pathParam:"style=simple,explode=false,name=id"` + Async *bool `default:"false" queryParam:"style=form,explode=true,name=async"` + ID string `pathParam:"style=simple,explode=false,name=id"` + SourceURL *bool `default:"false" queryParam:"style=form,explode=true,name=source_url"` // When passed true, the response will contain only fields that match the schema, with non-matching fields included in `__additional` Strict *bool `default:"false" queryParam:"style=form,explode=true,name=strict"` } @@ -41,6 +42,13 @@ func (o *GetFileRequest) GetID() string { return o.ID } +func (o *GetFileRequest) GetSourceURL() *bool { + if o == nil { + return nil + } + return o.SourceURL +} + func (o *GetFileRequest) GetStrict() *bool { if o == nil { return nil diff --git a/internal/sdk/models/operations/options.go b/internal/sdk/models/operations/options.go index 984085a..8894336 100644 --- a/internal/sdk/models/operations/options.go +++ b/internal/sdk/models/operations/options.go @@ -12,7 +12,6 @@ import ( var ErrUnsupportedOption = errors.New("unsupported option") const ( - SupportedOptionServerURL = "serverURL" SupportedOptionRetries = "retries" SupportedOptionTimeout = "timeout" SupportedOptionAcceptHeaderOverride = "acceptHeaderOverride" @@ -22,8 +21,8 @@ const ( type AcceptHeaderEnum string const ( - AcceptHeaderEnumApplicationJson AcceptHeaderEnum = "application/json" - AcceptHeaderEnumWildcardWildcard AcceptHeaderEnum = "*/*" + AcceptHeaderEnumApplicationJson AcceptHeaderEnum = "application/json" + AcceptHeaderEnumWildcardRootWildcard AcceptHeaderEnum = "*/*" ) func (e AcceptHeaderEnum) ToPointer() *AcceptHeaderEnum { @@ -36,6 +35,7 @@ type Options struct { Timeout *time.Duration AcceptHeaderOverride *AcceptHeaderEnum URLOverride *string + SetHeaders map[string]string } type Option func(*Options, ...string) error @@ -43,10 +43,6 @@ type Option func(*Options, ...string) error // WithServerURL allows providing an alternative server URL. func WithServerURL(serverURL string) Option { return func(opts *Options, supportedOptions ...string) error { - if !utils.Contains(supportedOptions, SupportedOptionServerURL) { - return ErrUnsupportedOption - } - opts.ServerURL = &serverURL return nil } @@ -55,10 +51,6 @@ func WithServerURL(serverURL string) Option { // WithTemplatedServerURL allows providing an alternative server URL with templated parameters. func WithTemplatedServerURL(serverURL string, params map[string]string) Option { return func(opts *Options, supportedOptions ...string) error { - if !utils.Contains(supportedOptions, SupportedOptionServerURL) { - return ErrUnsupportedOption - } - if params != nil { serverURL = utils.ReplaceParameters(serverURL, params) } @@ -114,3 +106,12 @@ func WithURLOverride(urlOverride string) Option { return nil } } + +// WithSetHeaders takes a map of headers that will applied to a request. If the +// request contains headers that are in the map then they will be overwritten. +func WithSetHeaders(hdrs map[string]string) Option { + return func(opts *Options, supportedOptions ...string) error { + opts.SetHeaders = hdrs + return nil + } +} diff --git a/internal/sdk/models/shared/fileentity.go b/internal/sdk/models/shared/fileentity.go index 710f620..7afc1dc 100644 --- a/internal/sdk/models/shared/fileentity.go +++ b/internal/sdk/models/shared/fileentity.go @@ -64,20 +64,20 @@ type FileEntity struct { // Access control list (ACL) for an entity. Defines sharing access to external orgs or users. ACL *BaseEntityACL `json:"_acl,omitempty"` CreatedAt *time.Time `json:"_created_at,omitempty"` - ID *string `json:"_id,omitempty"` + ID string `json:"_id"` // Manifest ID used to create/update the entity Manifest []string `json:"_manifest,omitempty"` - Org *string `json:"_org,omitempty"` + Org string `json:"_org"` Owners []BaseEntityOwner `json:"_owners,omitempty"` Purpose []string `json:"_purpose,omitempty"` - Schema *Schema `json:"_schema,omitempty"` + Schema Schema `json:"_schema"` Tags []string `json:"_tags,omitempty"` - Title *string `json:"_title,omitempty"` + Title string `json:"_title"` UpdatedAt *time.Time `json:"_updated_at,omitempty"` AccessControl *AccessControl `default:"private" json:"access_control"` // Custom external download url used for the file CustomDownloadURL *string `json:"custom_download_url,omitempty"` - Filename *string `json:"filename,omitempty"` + Filename string `json:"filename"` // MIME type of the file MimeType *string `json:"mime_type,omitempty"` // Direct URL for file (public only if file access control is public-read) @@ -89,8 +89,8 @@ type FileEntity struct { SizeBytes *int64 `json:"size_bytes,omitempty"` // Source URL for the file. Included if the entity was created from source_url, or when ?source_url=true SourceURL *string `json:"source_url,omitempty"` - Type *FileType `json:"type,omitempty"` - Versions []FileItem `json:"versions,omitempty"` + Type FileType `json:"type"` + Versions []FileItem `json:"versions"` } func (f FileEntity) MarshalJSON() ([]byte, error) { @@ -125,9 +125,9 @@ func (o *FileEntity) GetCreatedAt() *time.Time { return o.CreatedAt } -func (o *FileEntity) GetID() *string { +func (o *FileEntity) GetID() string { if o == nil { - return nil + return "" } return o.ID } @@ -139,9 +139,9 @@ func (o *FileEntity) GetManifest() []string { return o.Manifest } -func (o *FileEntity) GetOrg() *string { +func (o *FileEntity) GetOrg() string { if o == nil { - return nil + return "" } return o.Org } @@ -160,9 +160,9 @@ func (o *FileEntity) GetPurpose() []string { return o.Purpose } -func (o *FileEntity) GetSchema() *Schema { +func (o *FileEntity) GetSchema() Schema { if o == nil { - return nil + return Schema("") } return o.Schema } @@ -174,9 +174,9 @@ func (o *FileEntity) GetTags() []string { return o.Tags } -func (o *FileEntity) GetTitle() *string { +func (o *FileEntity) GetTitle() string { if o == nil { - return nil + return "" } return o.Title } @@ -202,9 +202,9 @@ func (o *FileEntity) GetCustomDownloadURL() *string { return o.CustomDownloadURL } -func (o *FileEntity) GetFilename() *string { +func (o *FileEntity) GetFilename() string { if o == nil { - return nil + return "" } return o.Filename } @@ -251,16 +251,16 @@ func (o *FileEntity) GetSourceURL() *string { return o.SourceURL } -func (o *FileEntity) GetType() *FileType { +func (o *FileEntity) GetType() FileType { if o == nil { - return nil + return FileType("") } return o.Type } func (o *FileEntity) GetVersions() []FileItem { if o == nil { - return nil + return []FileItem{} } return o.Versions } diff --git a/internal/sdk/models/shared/savecustomfilepayload.go b/internal/sdk/models/shared/savecustomfilepayload.go index 27f2497..45f2fd8 100644 --- a/internal/sdk/models/shared/savecustomfilepayload.go +++ b/internal/sdk/models/shared/savecustomfilepayload.go @@ -46,7 +46,7 @@ type SaveCustomFilePayload struct { CustomDownloadURL *string `json:"custom_download_url,omitempty"` // Deprecated, use _id instead // - // Deprecated field: This will be removed in a future release, please migrate away from it as soon as possible. + // Deprecated: This will be removed in a future release, please migrate away from it as soon as possible. FileEntityID *string `json:"file_entity_id,omitempty"` Filename *string `json:"filename,omitempty"` // MIME type of the file diff --git a/internal/sdk/models/shared/savefilefromsourceurlpayload.go b/internal/sdk/models/shared/savefilefromsourceurlpayload.go index d1b4c22..f76f61a 100644 --- a/internal/sdk/models/shared/savefilefromsourceurlpayload.go +++ b/internal/sdk/models/shared/savefilefromsourceurlpayload.go @@ -46,7 +46,7 @@ type SaveFileFromSourceURLPayload struct { CustomDownloadURL *string `json:"custom_download_url,omitempty"` // Deprecated, use _id instead // - // Deprecated field: This will be removed in a future release, please migrate away from it as soon as possible. + // Deprecated: This will be removed in a future release, please migrate away from it as soon as possible. FileEntityID *string `json:"file_entity_id,omitempty"` Filename *string `json:"filename,omitempty"` // MIME type of the file diff --git a/internal/sdk/models/shared/savefilepayload.go b/internal/sdk/models/shared/savefilepayload.go index 9d725b3..28b43e2 100644 --- a/internal/sdk/models/shared/savefilepayload.go +++ b/internal/sdk/models/shared/savefilepayload.go @@ -17,9 +17,9 @@ const ( ) type SaveFilePayload struct { - SaveS3FilePayload *SaveS3FilePayload - SaveFileFromSourceURLPayload *SaveFileFromSourceURLPayload - SaveCustomFilePayload *SaveCustomFilePayload + SaveS3FilePayload *SaveS3FilePayload `queryParam:"inline"` + SaveFileFromSourceURLPayload *SaveFileFromSourceURLPayload `queryParam:"inline"` + SaveCustomFilePayload *SaveCustomFilePayload `queryParam:"inline"` Type SaveFilePayloadType } diff --git a/internal/sdk/models/shared/savefilepayloadv2.go b/internal/sdk/models/shared/savefilepayloadv2.go index 08527a9..ae8d808 100644 --- a/internal/sdk/models/shared/savefilepayloadv2.go +++ b/internal/sdk/models/shared/savefilepayloadv2.go @@ -3,165 +3,92 @@ package shared import ( - "encoding/json" + "errors" "fmt" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/utils" ) -type SaveFilePayloadV2AccessControl string +type SaveFilePayloadV2Type string const ( - SaveFilePayloadV2AccessControlPrivate SaveFilePayloadV2AccessControl = "private" - SaveFilePayloadV2AccessControlPublicRead SaveFilePayloadV2AccessControl = "public-read" + SaveFilePayloadV2TypeSaveS3FilePayload SaveFilePayloadV2Type = "SaveS3FilePayload" + SaveFilePayloadV2TypeSaveFileFromSourceURLPayload SaveFilePayloadV2Type = "SaveFileFromSourceURLPayload" + SaveFilePayloadV2TypeSaveCustomFilePayload SaveFilePayloadV2Type = "SaveCustomFilePayload" ) -func (e SaveFilePayloadV2AccessControl) ToPointer() *SaveFilePayloadV2AccessControl { - return &e -} -func (e *SaveFilePayloadV2AccessControl) UnmarshalJSON(data []byte) error { - var v string - if err := json.Unmarshal(data, &v); err != nil { - return err - } - switch v { - case "private": - fallthrough - case "public-read": - *e = SaveFilePayloadV2AccessControl(v) - return nil - default: - return fmt.Errorf("invalid value for SaveFilePayloadV2AccessControl: %v", v) - } -} - type SaveFilePayloadV2 struct { - // Additional fields that are not part of the schema - Additional map[string]any `json:"__additional,omitempty"` - // Access control list (ACL) for an entity. Defines sharing access to external orgs or users. - ACL *BaseEntityACL `json:"_acl,omitempty"` - ID *string `json:"_id,omitempty"` - // Manifest ID used to create/update the entity - Manifest []string `json:"_manifest,omitempty"` - Purpose []string `json:"_purpose,omitempty"` - Tags []string `json:"_tags,omitempty"` - Title *string `json:"_title,omitempty"` - AccessControl *SaveFilePayloadV2AccessControl `default:"private" json:"access_control"` - // Custom external download url used for the file - CustomDownloadURL *string `json:"custom_download_url,omitempty"` - Filename *string `json:"filename,omitempty"` - // MIME type of the file - MimeType *string `json:"mime_type,omitempty"` - S3ref *S3Ref `json:"s3ref,omitempty"` - // Source URL for the file. Included if the entity was created from source_url, or when ?source_url=true - SourceURL *string `json:"source_url,omitempty"` - Type *FileType `json:"type,omitempty"` -} + SaveS3FilePayload *SaveS3FilePayload `queryParam:"inline"` + SaveFileFromSourceURLPayload *SaveFileFromSourceURLPayload `queryParam:"inline"` + SaveCustomFilePayload *SaveCustomFilePayload `queryParam:"inline"` -func (s SaveFilePayloadV2) MarshalJSON() ([]byte, error) { - return utils.MarshalJSON(s, "", false) + Type SaveFilePayloadV2Type } -func (s *SaveFilePayloadV2) UnmarshalJSON(data []byte) error { - if err := utils.UnmarshalJSON(data, &s, "", false, false); err != nil { - return err - } - return nil -} +func CreateSaveFilePayloadV2SaveS3FilePayload(saveS3FilePayload SaveS3FilePayload) SaveFilePayloadV2 { + typ := SaveFilePayloadV2TypeSaveS3FilePayload -func (o *SaveFilePayloadV2) GetAdditional() map[string]any { - if o == nil { - return nil + return SaveFilePayloadV2{ + SaveS3FilePayload: &saveS3FilePayload, + Type: typ, } - return o.Additional } -func (o *SaveFilePayloadV2) GetACL() *BaseEntityACL { - if o == nil { - return nil - } - return o.ACL -} +func CreateSaveFilePayloadV2SaveFileFromSourceURLPayload(saveFileFromSourceURLPayload SaveFileFromSourceURLPayload) SaveFilePayloadV2 { + typ := SaveFilePayloadV2TypeSaveFileFromSourceURLPayload -func (o *SaveFilePayloadV2) GetID() *string { - if o == nil { - return nil + return SaveFilePayloadV2{ + SaveFileFromSourceURLPayload: &saveFileFromSourceURLPayload, + Type: typ, } - return o.ID } -func (o *SaveFilePayloadV2) GetManifest() []string { - if o == nil { - return nil - } - return o.Manifest -} +func CreateSaveFilePayloadV2SaveCustomFilePayload(saveCustomFilePayload SaveCustomFilePayload) SaveFilePayloadV2 { + typ := SaveFilePayloadV2TypeSaveCustomFilePayload -func (o *SaveFilePayloadV2) GetPurpose() []string { - if o == nil { - return nil + return SaveFilePayloadV2{ + SaveCustomFilePayload: &saveCustomFilePayload, + Type: typ, } - return o.Purpose } -func (o *SaveFilePayloadV2) GetTags() []string { - if o == nil { - return nil - } - return o.Tags -} +func (u *SaveFilePayloadV2) UnmarshalJSON(data []byte) error { -func (o *SaveFilePayloadV2) GetTitle() *string { - if o == nil { + var saveCustomFilePayload SaveCustomFilePayload = SaveCustomFilePayload{} + if err := utils.UnmarshalJSON(data, &saveCustomFilePayload, "", true, true); err == nil { + u.SaveCustomFilePayload = &saveCustomFilePayload + u.Type = SaveFilePayloadV2TypeSaveCustomFilePayload return nil } - return o.Title -} -func (o *SaveFilePayloadV2) GetAccessControl() *SaveFilePayloadV2AccessControl { - if o == nil { + var saveS3FilePayload SaveS3FilePayload = SaveS3FilePayload{} + if err := utils.UnmarshalJSON(data, &saveS3FilePayload, "", true, true); err == nil { + u.SaveS3FilePayload = &saveS3FilePayload + u.Type = SaveFilePayloadV2TypeSaveS3FilePayload return nil } - return o.AccessControl -} -func (o *SaveFilePayloadV2) GetCustomDownloadURL() *string { - if o == nil { + var saveFileFromSourceURLPayload SaveFileFromSourceURLPayload = SaveFileFromSourceURLPayload{} + if err := utils.UnmarshalJSON(data, &saveFileFromSourceURLPayload, "", true, true); err == nil { + u.SaveFileFromSourceURLPayload = &saveFileFromSourceURLPayload + u.Type = SaveFilePayloadV2TypeSaveFileFromSourceURLPayload return nil } - return o.CustomDownloadURL -} -func (o *SaveFilePayloadV2) GetFilename() *string { - if o == nil { - return nil - } - return o.Filename + return fmt.Errorf("could not unmarshal `%s` into any supported union types for SaveFilePayloadV2", string(data)) } -func (o *SaveFilePayloadV2) GetMimeType() *string { - if o == nil { - return nil +func (u SaveFilePayloadV2) MarshalJSON() ([]byte, error) { + if u.SaveS3FilePayload != nil { + return utils.MarshalJSON(u.SaveS3FilePayload, "", true) } - return o.MimeType -} -func (o *SaveFilePayloadV2) GetS3ref() *S3Ref { - if o == nil { - return nil + if u.SaveFileFromSourceURLPayload != nil { + return utils.MarshalJSON(u.SaveFileFromSourceURLPayload, "", true) } - return o.S3ref -} -func (o *SaveFilePayloadV2) GetSourceURL() *string { - if o == nil { - return nil + if u.SaveCustomFilePayload != nil { + return utils.MarshalJSON(u.SaveCustomFilePayload, "", true) } - return o.SourceURL -} -func (o *SaveFilePayloadV2) GetType() *FileType { - if o == nil { - return nil - } - return o.Type + return nil, errors.New("could not marshal union type SaveFilePayloadV2: all fields are null") } diff --git a/internal/sdk/models/shared/saves3filepayload.go b/internal/sdk/models/shared/saves3filepayload.go index b0a7373..d036e2e 100644 --- a/internal/sdk/models/shared/saves3filepayload.go +++ b/internal/sdk/models/shared/saves3filepayload.go @@ -46,7 +46,7 @@ type SaveS3FilePayload struct { CustomDownloadURL *string `json:"custom_download_url,omitempty"` // Deprecated, use _id instead // - // Deprecated field: This will be removed in a future release, please migrate away from it as soon as possible. + // Deprecated: This will be removed in a future release, please migrate away from it as soon as possible. FileEntityID *string `json:"file_entity_id,omitempty"` Filename *string `json:"filename,omitempty"` // MIME type of the file diff --git a/internal/sdk/preview.go b/internal/sdk/preview.go index 31b2e44..85f2168 100644 --- a/internal/sdk/preview.go +++ b/internal/sdk/preview.go @@ -5,12 +5,10 @@ package sdk import ( "context" "fmt" - "github.com/cenkalti/backoff/v4" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/hooks" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/utils" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/errors" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/operations" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/retry" "net/http" "net/url" ) @@ -29,16 +27,8 @@ func newPreview(sdkConfig sdkConfiguration) *Preview { // PreviewFile - previewFile // Generate thumbnail preview for a file entity func (s *Preview) PreviewFile(ctx context.Context, request operations.PreviewFileRequest, opts ...operations.Option) (*operations.PreviewFileResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "previewFile", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -48,12 +38,25 @@ func (s *Preview) PreviewFile(ctx context.Context, request operations.PreviewFil } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := utils.GenerateURL(ctx, baseURL, "/v1/files/{id}/preview", request, nil) if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "previewFile", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -80,94 +83,36 @@ func (s *Preview) PreviewFile(ctx context.Context, request operations.PreviewFil return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -194,16 +139,8 @@ func (s *Preview) PreviewFile(ctx context.Context, request operations.PreviewFil // PreviewPublicFile - previewPublicFile // Generate thumbnail preview for a public file entity func (s *Preview) PreviewPublicFile(ctx context.Context, request operations.PreviewPublicFileRequest, opts ...operations.Option) (*operations.PreviewPublicFileResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "previewPublicFile", - OAuth2Scopes: []string{}, - SecuritySource: nil, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -213,12 +150,25 @@ func (s *Preview) PreviewPublicFile(ctx context.Context, request operations.Prev } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := utils.GenerateURL(ctx, baseURL, "/v1/files/public/{id}/preview", request, nil) if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "previewPublicFile", + OAuth2Scopes: []string{}, + SecuritySource: nil, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -241,94 +191,36 @@ func (s *Preview) PreviewPublicFile(ctx context.Context, request operations.Prev return nil, fmt.Errorf("error populating query params: %w", err) } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -355,16 +247,8 @@ func (s *Preview) PreviewPublicFile(ctx context.Context, request operations.Prev // PreviewS3File - previewS3File // Generate thumbnail preview from an s3 reference for a file entity func (s *Preview) PreviewS3File(ctx context.Context, request operations.PreviewS3FileRequest, opts ...operations.Option) (*operations.PreviewS3FileResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "previewS3File", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -374,12 +258,24 @@ func (s *Preview) PreviewS3File(ctx context.Context, request operations.PreviewS } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v1/files:previewS3") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "previewS3File", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, true, "S3Ref", "json", `request:"mediaType=application/json"`) if err != nil { return nil, err @@ -402,7 +298,9 @@ func (s *Preview) PreviewS3File(ctx context.Context, request operations.PreviewS } req.Header.Set("Accept", "*/*") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) - req.Header.Set("Content-Type", reqContentType) + if reqContentType != "" { + req.Header.Set("Content-Type", reqContentType) + } if err := utils.PopulateQueryParams(ctx, req, request, nil); err != nil { return nil, fmt.Errorf("error populating query params: %w", err) @@ -412,94 +310,36 @@ func (s *Preview) PreviewS3File(ctx context.Context, request operations.PreviewS return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -526,16 +366,8 @@ func (s *Preview) PreviewS3File(ctx context.Context, request operations.PreviewS // PreviewS3FileGet - previewS3FileGet // Get thumbnail preview from an s3 reference for a file entity func (s *Preview) PreviewS3FileGet(ctx context.Context, request operations.PreviewS3FileGetRequest, opts ...operations.Option) (*operations.PreviewS3FileGetResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "previewS3FileGet", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -545,12 +377,25 @@ func (s *Preview) PreviewS3FileGet(ctx context.Context, request operations.Previ } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v1/files:previewS3") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "previewS3FileGet", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -577,94 +422,36 @@ func (s *Preview) PreviewS3FileGet(ctx context.Context, request operations.Previ return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } diff --git a/internal/sdk/publiclinks.go b/internal/sdk/publiclinks.go index fabc7b6..9197b0a 100644 --- a/internal/sdk/publiclinks.go +++ b/internal/sdk/publiclinks.go @@ -6,12 +6,10 @@ import ( "bytes" "context" "fmt" - "github.com/cenkalti/backoff/v4" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/hooks" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/utils" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/errors" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/operations" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/retry" "net/http" ) @@ -29,16 +27,8 @@ func newPublicLinks(sdkConfig sdkConfiguration) *PublicLinks { // AccessPublicLink - accessPublicLink // Redirects to a accessible signed url for the respective file associated to the public link func (s *PublicLinks) AccessPublicLink(ctx context.Context, request operations.AccessPublicLinkRequest, opts ...operations.Option) (*operations.AccessPublicLinkResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "accessPublicLink", - OAuth2Scopes: []string{}, - SecuritySource: nil, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -48,12 +38,25 @@ func (s *PublicLinks) AccessPublicLink(ctx context.Context, request operations.A } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := utils.GenerateURL(ctx, baseURL, "/v1/files/public/links/{id}/{filename}", request, nil) if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "accessPublicLink", + OAuth2Scopes: []string{}, + SecuritySource: nil, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -72,94 +75,40 @@ func (s *PublicLinks) AccessPublicLink(ctx context.Context, request operations.A req.Header.Set("Accept", "*/*") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + if err := utils.PopulateQueryParams(ctx, req, request, nil); err != nil { + return nil, fmt.Errorf("error populating query params: %w", err) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) + } - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -186,16 +135,8 @@ func (s *PublicLinks) AccessPublicLink(ctx context.Context, request operations.A // GeneratePublicLink - generatePublicLink // Generates a public link to access a private file func (s *PublicLinks) GeneratePublicLink(ctx context.Context, request operations.GeneratePublicLinkRequest, opts ...operations.Option) (*operations.GeneratePublicLinkResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "generatePublicLink", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -205,12 +146,25 @@ func (s *PublicLinks) GeneratePublicLink(ctx context.Context, request operations } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := utils.GenerateURL(ctx, baseURL, "/v1/files/{id}/public/links", request, nil) if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "generatePublicLink", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -233,94 +187,36 @@ func (s *PublicLinks) GeneratePublicLink(ctx context.Context, request operations return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -367,16 +263,8 @@ func (s *PublicLinks) GeneratePublicLink(ctx context.Context, request operations // ListPublicLinksForFile - listPublicLinksForFile // Not yet implemented; This API would fetch all the public links that are previously generated for a file func (s *PublicLinks) ListPublicLinksForFile(ctx context.Context, request operations.ListPublicLinksForFileRequest, opts ...operations.Option) (*operations.ListPublicLinksForFileResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "listPublicLinksForFile", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -386,12 +274,25 @@ func (s *PublicLinks) ListPublicLinksForFile(ctx context.Context, request operat } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := utils.GenerateURL(ctx, baseURL, "/v1/files/{id}/public/links", request, nil) if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "listPublicLinksForFile", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -414,94 +315,36 @@ func (s *PublicLinks) ListPublicLinksForFile(ctx context.Context, request operat return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -548,16 +391,8 @@ func (s *PublicLinks) ListPublicLinksForFile(ctx context.Context, request operat // RevokePublicLink - revokePublicLink // Not yet implemented; This operation would revoke a given public link by ID func (s *PublicLinks) RevokePublicLink(ctx context.Context, request operations.RevokePublicLinkRequest, opts ...operations.Option) (*operations.RevokePublicLinkResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "revokePublicLink", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -567,12 +402,25 @@ func (s *PublicLinks) RevokePublicLink(ctx context.Context, request operations.R } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := utils.GenerateURL(ctx, baseURL, "/v1/files/public/links/{id}", request, nil) if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "revokePublicLink", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -595,94 +443,36 @@ func (s *PublicLinks) RevokePublicLink(ctx context.Context, request operations.R return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } diff --git a/internal/sdk/retry/config.go b/internal/sdk/retry/config.go index c051b0a..aa809fc 100644 --- a/internal/sdk/retry/config.go +++ b/internal/sdk/retry/config.go @@ -2,6 +2,15 @@ package retry +import ( + "errors" + "net/http" + "strconv" + "time" +) + +// BackoffStrategy defines the parameters for exponential backoff. This can be +// used to drive a retry loop for example. type BackoffStrategy struct { InitialInterval int MaxInterval int @@ -9,8 +18,131 @@ type BackoffStrategy struct { MaxElapsedTime int } +// Config configures a retry policy. type Config struct { + // Strategy sets the algorithm to use for a retry loop. It can be one of: + // - "backoff": retry with exponential backoff and random jitter. + // - "none" or "": disables retries. Strategy string Backoff *BackoffStrategy RetryConnectionErrors bool } + +// PermanentError is an error that signals that some operation has terminally +// failed and should not be retried. +type PermanentError struct { + cause error +} + +// Permanent creates a PermanentError that signals to a retry loop that it +// should stop retrying an operation and return the underlying error. +func Permanent(cause error) error { + if IsPermanentError(cause) { + return cause + } + + return &PermanentError{ + cause: cause, + } +} + +func (e *PermanentError) Error() string { + return e.cause.Error() +} + +func (e *PermanentError) Unwrap() error { + return e.cause +} + +// TemporaryError represents a retryable error and signals to a retry loop that +// an operation may be retried with an optional wait interval. +type TemporaryError struct { + wait time.Duration + message string +} + +// Temporary creates a TemporaryError that signals to a retry loop that an +// operation can be retried. The error may also carry details about how long to +// wait before retrying. This wait interval may be used to override the retry +// policy in use. +func Temporary(message string) error { + return &TemporaryError{ + message: message, + } +} + +// TemporaryFromResponse creates a TemporaryError similar to Temporary but +// additionally parses the Retry-After header from a response to determine the +// wait interval before the next retry attempt. +func TemporaryFromResponse(message string, res *http.Response) error { + return &TemporaryError{ + wait: retryIntervalFromResponse(res), + message: message, + } +} + +func (e *TemporaryError) Error() string { + return e.message +} + +// RetryAfter returns the time to wait before retrying the request. The zero +// value should be interpreted by retry loops to mean they should fallback on +// their default policy whether expenonential, constant backoff or something +// else. It does not mean that an operation should be retried immediately. +func (e *TemporaryError) RetryAfter() time.Duration { + return e.wait +} + +func retryIntervalFromResponse(res *http.Response) time.Duration { + if res == nil { + return 0 + } + + retryVal := res.Header.Get("retry-after") + if retryVal == "" { + return 0 + } + + parsedNumber, err := strconv.ParseInt(retryVal, 10, 64) + if err == nil { + if parsedNumber < 0 { + return 0 + } else { + return time.Duration(parsedNumber) * time.Second + } + } + + parsedDate, err := time.Parse(time.RFC1123, retryVal) + if err == nil { + delta := parsedDate.Sub(time.Now()) + if delta < 0 { + return 0 + } else { + return delta + } + } + + return 0 +} + +// IsPermanentError returns true if an error value is or contains a +// PermanentError in its chain of errors. +func IsPermanentError(err error) bool { + if err == nil { + return false + } + + var pe *PermanentError + return errors.As(err, &pe) +} + +// IsTemporaryError returns true if an error value is or contains a +// TemporaryError in its chain of errors. +func IsTemporaryError(err error) bool { + if err == nil { + return false + } + + var pe *TemporaryError + return errors.As(err, &pe) +} diff --git a/internal/sdk/sdk.go b/internal/sdk/sdk.go index 465b28f..1ff5b2a 100644 --- a/internal/sdk/sdk.go +++ b/internal/sdk/sdk.go @@ -156,9 +156,9 @@ func New(opts ...SDKOption) *SDK { sdkConfiguration: sdkConfiguration{ Language: "go", OpenAPIDocVersion: "0.2.0", - SDKVersion: "0.0.1", - GenVersion: "2.438.15", - UserAgent: "speakeasy-sdk/go 0.0.1 2.438.15 0.2.0 github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk", + SDKVersion: "0.6.0", + GenVersion: "2.593.3", + UserAgent: "speakeasy-sdk/terraform 0.6.0 2.593.3 0.2.0 github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk", Hooks: hooks.New(), }, } diff --git a/internal/sdk/session.go b/internal/sdk/session.go index e802025..6cfb3fa 100644 --- a/internal/sdk/session.go +++ b/internal/sdk/session.go @@ -5,12 +5,10 @@ package sdk import ( "context" "fmt" - "github.com/cenkalti/backoff/v4" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/hooks" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/internal/utils" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/errors" "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/models/operations" - "github.com/epilot-dev/terraform-provider-epilot-file/internal/sdk/retry" "net/http" "net/url" ) @@ -29,16 +27,8 @@ func newSession(sdkConfig sdkConfiguration) *Session { // DeleteSession - deleteSession // End browser session by deleting token cookie func (s *Session) DeleteSession(ctx context.Context, opts ...operations.Option) (*operations.DeleteSessionResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "deleteSession", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -48,12 +38,25 @@ func (s *Session) DeleteSession(ctx context.Context, opts ...operations.Option) } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v1/files/session") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "deleteSession", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -76,94 +79,36 @@ func (s *Session) DeleteSession(ctx context.Context, opts ...operations.Option) return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } @@ -192,16 +137,8 @@ func (s *Session) DeleteSession(ctx context.Context, opts ...operations.Option) // // Allows using preview urls directly in img src for private files using cookie authentication. func (s *Session) GetSession(ctx context.Context, opts ...operations.Option) (*operations.GetSessionResponse, error) { - hookCtx := hooks.HookContext{ - Context: ctx, - OperationID: "getSession", - OAuth2Scopes: []string{}, - SecuritySource: s.sdkConfiguration.Security, - } - o := operations.Options{} supportedOptions := []string{ - operations.SupportedOptionRetries, operations.SupportedOptionTimeout, } @@ -211,12 +148,25 @@ func (s *Session) GetSession(ctx context.Context, opts ...operations.Option) (*o } } - baseURL := utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + var baseURL string + if o.ServerURL == nil { + baseURL = utils.ReplaceParameters(s.sdkConfiguration.GetServerDetails()) + } else { + baseURL = *o.ServerURL + } opURL, err := url.JoinPath(baseURL, "/v1/files/session") if err != nil { return nil, fmt.Errorf("error generating URL: %w", err) } + hookCtx := hooks.HookContext{ + BaseURL: baseURL, + Context: ctx, + OperationID: "getSession", + OAuth2Scopes: []string{}, + SecuritySource: s.sdkConfiguration.Security, + } + timeout := o.Timeout if timeout == nil { timeout = s.sdkConfiguration.Timeout @@ -239,94 +189,36 @@ func (s *Session) GetSession(ctx context.Context, opts ...operations.Option) (*o return nil, err } - globalRetryConfig := s.sdkConfiguration.RetryConfig - retryConfig := o.Retries - if retryConfig == nil { - if globalRetryConfig != nil { - retryConfig = globalRetryConfig - } else { - retryConfig = &retry.Config{ - Strategy: "backoff", Backoff: &retry.BackoffStrategy{ - InitialInterval: 5000, - MaxInterval: 60000, - Exponent: 1.5, - MaxElapsedTime: 3600000, - }, - RetryConnectionErrors: true, - } - } + for k, v := range o.SetHeaders { + req.Header.Set(k, v) } - var httpRes *http.Response - if retryConfig != nil { - httpRes, err = utils.Retry(ctx, utils.Retries{ - Config: retryConfig, - StatusCodes: []string{ - "5XX", - }, - }, func() (*http.Response, error) { - if req.Body != nil { - copyBody, err := req.GetBody() - if err != nil { - return nil, err - } - req.Body = copyBody - } - - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) - if err != nil { - return nil, backoff.Permanent(err) - } - - httpRes, err := s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) - } - return httpRes, err - }) + req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + if err != nil { + return nil, err + } + httpRes, err := s.sdkConfiguration.Client.Do(req) + if err != nil || httpRes == nil { if err != nil { - return nil, err + err = fmt.Errorf("error sending request: %w", err) } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } + err = fmt.Errorf("error sending request: no response") } - } else { - req, err = s.sdkConfiguration.Hooks.BeforeRequest(hooks.BeforeRequestContext{HookContext: hookCtx}, req) + + _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + return nil, err + } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { + _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) if err != nil { return nil, err + } else if _httpRes != nil { + httpRes = _httpRes } - - httpRes, err = s.sdkConfiguration.Client.Do(req) - if err != nil || httpRes == nil { - if err != nil { - err = fmt.Errorf("error sending request: %w", err) - } else { - err = fmt.Errorf("error sending request: no response") - } - - _, err = s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, nil, err) + } else { + httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) + if err != nil { return nil, err - } else if utils.MatchStatusCodes([]string{}, httpRes.StatusCode) { - _httpRes, err := s.sdkConfiguration.Hooks.AfterError(hooks.AfterErrorContext{HookContext: hookCtx}, httpRes, nil) - if err != nil { - return nil, err - } else if _httpRes != nil { - httpRes = _httpRes - } - } else { - httpRes, err = s.sdkConfiguration.Hooks.AfterSuccess(hooks.AfterSuccessContext{HookContext: hookCtx}, httpRes) - if err != nil { - return nil, err - } } } diff --git a/internal/validators/float32validators/not_null.go b/internal/validators/float32validators/not_null.go new file mode 100644 index 0000000..c9a8973 --- /dev/null +++ b/internal/validators/float32validators/not_null.go @@ -0,0 +1,49 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package float32validators + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/schema/validator" +) + +var _ validator.Float32 = Float32NotNullValidator{} + +// Float32NotNullValidator validates that an attribute is not null. Most +// attributes should set Required: true instead, however in certain scenarios, +// such as a computed nested attribute, all underlying attributes must also be +// computed for planning to not show unexpected differences. +type Float32NotNullValidator struct{} + +// Description describes the validation in plain text formatting. +func (v Float32NotNullValidator) Description(_ context.Context) string { + return "value must be configured" +} + +// MarkdownDescription describes the validation in Markdown formatting. +func (v Float32NotNullValidator) MarkdownDescription(ctx context.Context) string { + return v.Description(ctx) +} + +// Validate performs the validation. +func (v Float32NotNullValidator) ValidateFloat32(ctx context.Context, req validator.Float32Request, resp *validator.Float32Response) { + if !req.ConfigValue.IsNull() { + return + } + + resp.Diagnostics.AddAttributeError( + req.Path, + "Missing Attribute Value", + req.Path.String()+": "+v.Description(ctx), + ) +} + +// NotNull returns an validator which ensures that the attribute is +// configured. Most attributes should set Required: true instead, however in +// certain scenarios, such as a computed nested attribute, all underlying +// attributes must also be computed for planning to not show unexpected +// differences. +func NotNull() validator.Float32 { + return Float32NotNullValidator{} +} diff --git a/internal/validators/int32validators/not_null.go b/internal/validators/int32validators/not_null.go new file mode 100644 index 0000000..ec9a3f1 --- /dev/null +++ b/internal/validators/int32validators/not_null.go @@ -0,0 +1,49 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package int32validators + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/schema/validator" +) + +var _ validator.Int32 = Int32NotNullValidator{} + +// Int32NotNullValidator validates that an attribute is not null. Most +// attributes should set Required: true instead, however in certain scenarios, +// such as a computed nested attribute, all underlying attributes must also be +// computed for planning to not show unexpected differences. +type Int32NotNullValidator struct{} + +// Description describes the validation in plain text formatting. +func (v Int32NotNullValidator) Description(_ context.Context) string { + return "value must be configured" +} + +// MarkdownDescription describes the validation in Markdown formatting. +func (v Int32NotNullValidator) MarkdownDescription(ctx context.Context) string { + return v.Description(ctx) +} + +// Validate performs the validation. +func (v Int32NotNullValidator) ValidateInt32(ctx context.Context, req validator.Int32Request, resp *validator.Int32Response) { + if !req.ConfigValue.IsNull() { + return + } + + resp.Diagnostics.AddAttributeError( + req.Path, + "Missing Attribute Value", + req.Path.String()+": "+v.Description(ctx), + ) +} + +// NotNull returns an validator which ensures that the attribute is +// configured. Most attributes should set Required: true instead, however in +// certain scenarios, such as a computed nested attribute, all underlying +// attributes must also be computed for planning to not show unexpected +// differences. +func NotNull() validator.Int32 { + return Int32NotNullValidator{} +}