From 3f7028534390ba05d3d53a5ef73bec27407e0ddb Mon Sep 17 00:00:00 2001 From: Thomas Kappler Date: Wed, 20 Nov 2024 09:09:37 +0100 Subject: [PATCH 1/2] Correctly handle blob MD5 sums in custom blob resource, need to be base64-encoded --- provider/pkg/gen/__snapshots__/gen_vnet_test.snap | 2 +- .../customresources/custom_storage_azidentity.go | 11 ++++++++--- .../customresources/custom_storage_azidentity_test.go | 2 ++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/provider/pkg/gen/__snapshots__/gen_vnet_test.snap b/provider/pkg/gen/__snapshots__/gen_vnet_test.snap index 658999567132..af68b18888f5 100755 --- a/provider/pkg/gen/__snapshots__/gen_vnet_test.snap +++ b/provider/pkg/gen/__snapshots__/gen_vnet_test.snap @@ -24185,7 +24185,7 @@ "willReplaceOnChanges": true }, "contentMd5": { - "description": "The MD5 sum of the blob contents. Cannot be defined if blob type is Append.", + "description": "The MD5 sum of the blob contents, base64-encoded. Cannot be defined if blob type is Append.", "type": "string", "willReplaceOnChanges": true }, diff --git a/provider/pkg/resources/customresources/custom_storage_azidentity.go b/provider/pkg/resources/customresources/custom_storage_azidentity.go index fa43c23065dd..3a9cb35d8117 100644 --- a/provider/pkg/resources/customresources/custom_storage_azidentity.go +++ b/provider/pkg/resources/customresources/custom_storage_azidentity.go @@ -4,6 +4,7 @@ package customresources import ( "context" + "encoding/base64" "fmt" "net/http" neturl "net/url" @@ -348,7 +349,7 @@ func getBlobSchema() *schema.ResourceSpec { WillReplaceOnChanges: true, }, contentMd5: { - Description: "The MD5 sum of the blob contents. Cannot be defined if blob type is Append.", + Description: "The MD5 sum of the blob contents, base64-encoded. Cannot be defined if blob type is Append.", TypeSpec: schema.TypeSpec{Type: "string"}, WillReplaceOnChanges: true, }, @@ -560,7 +561,11 @@ func (r *blob_azidentity) create(ctx context.Context, id string, properties reso if properties[contentMd5].HasValue() { md5 := properties[contentMd5].StringValue() - opts.HTTPHeaders.BlobContentMD5 = []byte(md5) + md5Bytes, err := base64.StdEncoding.DecodeString(md5) + if err != nil { + return nil, err + } + opts.HTTPHeaders.BlobContentMD5 = md5Bytes } input := []byte{} @@ -706,7 +711,7 @@ func azblobToPulumiProperties(name, rg, account, container, azureResourceId stri containerName: container, blobName: name, nameProp: name, - contentMd5: fmt.Sprintf("%x", props.ContentMD5), // the binary hash needs to be hex-encoded + contentMd5: base64.StdEncoding.EncodeToString(props.ContentMD5), contentType: *props.ContentType, metadata: props.Metadata, typeProp: strings.TrimSuffix(string(*props.BlobType), "Blob"), diff --git a/provider/pkg/resources/customresources/custom_storage_azidentity_test.go b/provider/pkg/resources/customresources/custom_storage_azidentity_test.go index 26094f677b3c..d7f75c78c02d 100644 --- a/provider/pkg/resources/customresources/custom_storage_azidentity_test.go +++ b/provider/pkg/resources/customresources/custom_storage_azidentity_test.go @@ -2,6 +2,7 @@ package customresources import ( "crypto/md5" + "encoding/base64" "testing" "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" @@ -151,6 +152,7 @@ func TestAzblobToPulumiProperties(t *testing.T) { assert.Equal(t, "Block", pulumiBlob[typeProp]) assert.Contains(t, pulumiBlob, contentMd5) + assert.Equal(t, base64.StdEncoding.EncodeToString(azblob.ContentMD5), pulumiBlob[contentMd5]) assert.Contains(t, pulumiBlob, contentType) assert.Equal(t, "text/plain", pulumiBlob[contentType]) From 29dcfeeb503c490facfba98a170630f27e4a2314 Mon Sep 17 00:00:00 2001 From: Thomas Kappler Date: Wed, 20 Nov 2024 11:25:56 +0100 Subject: [PATCH 2/2] regenerate --- provider/cmd/pulumi-resource-azure-native/schema.json | 4 ++-- sdk/dotnet/Storage/Blob.cs | 2 +- sdk/nodejs/storage/blob.ts | 2 +- sdk/python/pulumi_azure_native/storage/blob.py | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/provider/cmd/pulumi-resource-azure-native/schema.json b/provider/cmd/pulumi-resource-azure-native/schema.json index f24472a03593..ea54bdd71dbf 100644 --- a/provider/cmd/pulumi-resource-azure-native/schema.json +++ b/provider/cmd/pulumi-resource-azure-native/schema.json @@ -627326,7 +627326,7 @@ ] }, "azure-native:datamigration:ServiceTask": { - "description": "A task resource\nAzure REST API version: 2021-06-30.\n\nOther available API versions: 2022-03-30-preview, 2023-07-15-preview.\n\n{{% examples %}}\n## Example Usage\n{{% example %}}\n### Tasks_CreateOrUpdate\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing AzureNative = Pulumi.AzureNative;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n var serviceTask = new AzureNative.DataMigration.ServiceTask(\"serviceTask\", new()\n {\n GroupName = \"DmsSdkRg\",\n Properties = \n {\n { \"input\", new AzureNative.DataMigration.Inputs.MongoDbConnectionInfoArgs\n {\n ServerVersion = \"NA\",\n } },\n { \"taskType\", \"Service.Check.OCI\" },\n },\n ServiceName = \"DmsSdkService\",\n TaskName = \"DmsSdkTask\",\n });\n\n});\n\n\n```\n\n```go\npackage main\n\nimport (\n\tdatamigration \"github.com/pulumi/pulumi-azure-native-sdk/datamigration/v2\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\nfunc main() {\npulumi.Run(func(ctx *pulumi.Context) error {\n_, err := datamigration.NewServiceTask(ctx, \"serviceTask\", \u0026datamigration.ServiceTaskArgs{\nGroupName: pulumi.String(\"DmsSdkRg\"),\nProperties: interface{}{\nInput: \u0026datamigration.MongoDbConnectionInfoArgs{\nServerVersion: \"NA\",\n},\nTaskType: pulumi.String(\"Service.Check.OCI\"),\n},\nServiceName: pulumi.String(\"DmsSdkService\"),\nTaskName: pulumi.String(\"DmsSdkTask\"),\n})\nif err != nil {\nreturn err\n}\nreturn nil\n})\n}\n\n```\n\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.azurenative.datamigration.ServiceTask;\nimport com.pulumi.azurenative.datamigration.ServiceTaskArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n public static void main(String[] args) {\n Pulumi.run(App::stack);\n }\n\n public static void stack(Context ctx) {\n var serviceTask = new ServiceTask(\"serviceTask\", ServiceTaskArgs.builder()\n .groupName(\"DmsSdkRg\")\n .properties(ConnectToMongoDbTaskPropertiesArgs.builder()\n .input(MongoDbConnectionInfoArgs.builder()\n .serverVersion(\"NA\")\n .build())\n .taskType(\"Service.Check.OCI\")\n .build())\n .serviceName(\"DmsSdkService\")\n .taskName(\"DmsSdkTask\")\n .build());\n\n }\n}\n\n```\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as azure_native from \"@pulumi/azure-native\";\n\nconst serviceTask = new azure_native.datamigration.ServiceTask(\"serviceTask\", {\n groupName: \"DmsSdkRg\",\n properties: {\n input: {\n serverVersion: \"NA\",\n },\n taskType: \"Service.Check.OCI\",\n },\n serviceName: \"DmsSdkService\",\n taskName: \"DmsSdkTask\",\n});\n\n```\n\n```python\nimport pulumi\nimport pulumi_azure_native as azure_native\n\nservice_task = azure_native.datamigration.ServiceTask(\"serviceTask\",\n group_name=\"DmsSdkRg\",\n properties={\n \"input\": {\n \"server_version\": \"NA\",\n },\n \"task_type\": \"Service.Check.OCI\",\n },\n service_name=\"DmsSdkService\",\n task_name=\"DmsSdkTask\")\n\n```\n\n```yaml\nresources:\n serviceTask:\n type: azure-native:datamigration:ServiceTask\n properties:\n groupName: DmsSdkRg\n properties:\n input:\n serverVersion: NA\n taskType: Service.Check.OCI\n serviceName: DmsSdkService\n taskName: DmsSdkTask\n\n```\n\n{{% /example %}}\n{{% /examples %}}\n\n## Import\n\nAn existing resource can be imported using its type token, name, and identifier, e.g.\n\n```sh\n$ pulumi import azure-native:datamigration:ServiceTask DmsSdkTask /subscriptions/{subscriptionId}/resourceGroups/{groupName}/providers/Microsoft.DataMigration/services/{serviceName}/serviceTasks/{taskName} \n```\n", + "description": "A task resource\nAzure REST API version: 2021-06-30.\n\nOther available API versions: 2022-03-30-preview, 2023-07-15-preview.\n\n{{% examples %}}\n## Example Usage\n{{% example %}}\n### Tasks_CreateOrUpdate\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing AzureNative = Pulumi.AzureNative;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n var serviceTask = new AzureNative.DataMigration.ServiceTask(\"serviceTask\", new()\n {\n GroupName = \"DmsSdkRg\",\n Properties = \n {\n { \"input\", new AzureNative.DataMigration.Inputs.ConnectToSourcePostgreSqlSyncTaskInputArgs\n {\n ServerVersion = \"NA\",\n } },\n { \"taskType\", \"Service.Check.OCI\" },\n },\n ServiceName = \"DmsSdkService\",\n TaskName = \"DmsSdkTask\",\n });\n\n});\n\n\n```\n\n```go\npackage main\n\nimport (\n\tdatamigration \"github.com/pulumi/pulumi-azure-native-sdk/datamigration/v2\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\nfunc main() {\npulumi.Run(func(ctx *pulumi.Context) error {\n_, err := datamigration.NewServiceTask(ctx, \"serviceTask\", \u0026datamigration.ServiceTaskArgs{\nGroupName: pulumi.String(\"DmsSdkRg\"),\nProperties: interface{}{\nInput: \u0026datamigration.MongoDbConnectionInfoArgs{\nServerVersion: \"NA\",\n},\nTaskType: pulumi.String(\"Service.Check.OCI\"),\n},\nServiceName: pulumi.String(\"DmsSdkService\"),\nTaskName: pulumi.String(\"DmsSdkTask\"),\n})\nif err != nil {\nreturn err\n}\nreturn nil\n})\n}\n\n```\n\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.azurenative.datamigration.ServiceTask;\nimport com.pulumi.azurenative.datamigration.ServiceTaskArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n public static void main(String[] args) {\n Pulumi.run(App::stack);\n }\n\n public static void stack(Context ctx) {\n var serviceTask = new ServiceTask(\"serviceTask\", ServiceTaskArgs.builder()\n .groupName(\"DmsSdkRg\")\n .properties(ConnectToMongoDbTaskPropertiesArgs.builder()\n .input(MongoDbConnectionInfoArgs.builder()\n .serverVersion(\"NA\")\n .build())\n .taskType(\"Service.Check.OCI\")\n .build())\n .serviceName(\"DmsSdkService\")\n .taskName(\"DmsSdkTask\")\n .build());\n\n }\n}\n\n```\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as azure_native from \"@pulumi/azure-native\";\n\nconst serviceTask = new azure_native.datamigration.ServiceTask(\"serviceTask\", {\n groupName: \"DmsSdkRg\",\n properties: {\n input: {\n serverVersion: \"NA\",\n },\n taskType: \"Service.Check.OCI\",\n },\n serviceName: \"DmsSdkService\",\n taskName: \"DmsSdkTask\",\n});\n\n```\n\n```python\nimport pulumi\nimport pulumi_azure_native as azure_native\n\nservice_task = azure_native.datamigration.ServiceTask(\"serviceTask\",\n group_name=\"DmsSdkRg\",\n properties={\n \"input\": {\n \"server_version\": \"NA\",\n },\n \"task_type\": \"Service.Check.OCI\",\n },\n service_name=\"DmsSdkService\",\n task_name=\"DmsSdkTask\")\n\n```\n\n```yaml\nresources:\n serviceTask:\n type: azure-native:datamigration:ServiceTask\n properties:\n groupName: DmsSdkRg\n properties:\n input:\n serverVersion: NA\n taskType: Service.Check.OCI\n serviceName: DmsSdkService\n taskName: DmsSdkTask\n\n```\n\n{{% /example %}}\n{{% /examples %}}\n\n## Import\n\nAn existing resource can be imported using its type token, name, and identifier, e.g.\n\n```sh\n$ pulumi import azure-native:datamigration:ServiceTask DmsSdkTask /subscriptions/{subscriptionId}/resourceGroups/{groupName}/providers/Microsoft.DataMigration/services/{serviceName}/serviceTasks/{taskName} \n```\n", "properties": { "etag": { "type": "string", @@ -797243,7 +797243,7 @@ }, "contentMd5": { "type": "string", - "description": "The MD5 sum of the blob contents. Cannot be defined if blob type is Append.", + "description": "The MD5 sum of the blob contents, base64-encoded. Cannot be defined if blob type is Append.", "willReplaceOnChanges": true }, "contentType": { diff --git a/sdk/dotnet/Storage/Blob.cs b/sdk/dotnet/Storage/Blob.cs index 0eb1728ce398..a92086b621ee 100644 --- a/sdk/dotnet/Storage/Blob.cs +++ b/sdk/dotnet/Storage/Blob.cs @@ -127,7 +127,7 @@ public sealed class BlobArgs : global::Pulumi.ResourceArgs public Input ContainerName { get; set; } = null!; /// - /// The MD5 sum of the blob contents. Cannot be defined if blob type is Append. + /// The MD5 sum of the blob contents, base64-encoded. Cannot be defined if blob type is Append. /// [Input("contentMd5")] public Input? ContentMd5 { get; set; } diff --git a/sdk/nodejs/storage/blob.ts b/sdk/nodejs/storage/blob.ts index a7a6e1abc038..d6e851c9954c 100644 --- a/sdk/nodejs/storage/blob.ts +++ b/sdk/nodejs/storage/blob.ts @@ -133,7 +133,7 @@ export interface BlobArgs { */ containerName: pulumi.Input; /** - * The MD5 sum of the blob contents. Cannot be defined if blob type is Append. + * The MD5 sum of the blob contents, base64-encoded. Cannot be defined if blob type is Append. */ contentMd5?: pulumi.Input; /** diff --git a/sdk/python/pulumi_azure_native/storage/blob.py b/sdk/python/pulumi_azure_native/storage/blob.py index f824f7667406..1626b4ea13d2 100644 --- a/sdk/python/pulumi_azure_native/storage/blob.py +++ b/sdk/python/pulumi_azure_native/storage/blob.py @@ -37,7 +37,7 @@ def __init__(__self__, *, :param pulumi.Input[str] resource_group_name: The name of the resource group within the user's subscription. :param pulumi.Input['BlobAccessTier'] access_tier: The access tier of the storage blob. Only supported for standard storage accounts, not premium. :param pulumi.Input[str] blob_name: The name of the storage blob. Must be unique within the storage container the blob is located. If this property is not specified it will be set to the name of the resource. - :param pulumi.Input[str] content_md5: The MD5 sum of the blob contents. Cannot be defined if blob type is Append. + :param pulumi.Input[str] content_md5: The MD5 sum of the blob contents, base64-encoded. Cannot be defined if blob type is Append. :param pulumi.Input[str] content_type: The content type of the storage blob. Defaults to `application/octet-stream`. :param pulumi.Input[Mapping[str, pulumi.Input[str]]] metadata: A map of custom blob metadata. :param pulumi.Input[Union[pulumi.Asset, pulumi.Archive]] source: An asset to copy to the blob contents. This field cannot be specified for Append blobs. @@ -127,7 +127,7 @@ def blob_name(self, value: Optional[pulumi.Input[str]]): @pulumi.getter(name="contentMd5") def content_md5(self) -> Optional[pulumi.Input[str]]: """ - The MD5 sum of the blob contents. Cannot be defined if blob type is Append. + The MD5 sum of the blob contents, base64-encoded. Cannot be defined if blob type is Append. """ return pulumi.get(self, "content_md5") @@ -209,7 +209,7 @@ def __init__(__self__, :param pulumi.Input[str] account_name: Specifies the storage account in which to create the storage container. :param pulumi.Input[str] blob_name: The name of the storage blob. Must be unique within the storage container the blob is located. If this property is not specified it will be set to the name of the resource. :param pulumi.Input[str] container_name: The name of the storage container in which this blob should be created. - :param pulumi.Input[str] content_md5: The MD5 sum of the blob contents. Cannot be defined if blob type is Append. + :param pulumi.Input[str] content_md5: The MD5 sum of the blob contents, base64-encoded. Cannot be defined if blob type is Append. :param pulumi.Input[str] content_type: The content type of the storage blob. Defaults to `application/octet-stream`. :param pulumi.Input[Mapping[str, pulumi.Input[str]]] metadata: A map of custom blob metadata. :param pulumi.Input[str] resource_group_name: The name of the resource group within the user's subscription.