diff --git a/.claude/settings.json b/.claude/settings.json index 9c7f2a82..ec7463e0 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -14,6 +14,7 @@ "Bash(az monitor log-analytics workspace table list:*)", "Bash(az monitor log-analytics workspace table show:*)", "Bash(az role assignment list:*)", + "Bash(az role assignment show:*)", "Bash(cat:*)", "Bash(curl -sf http://localhost:*)", "Bash(diff:*)", diff --git a/cd/main_test.go b/cd/main_test.go index 46f479ba..eb05eb78 100644 --- a/cd/main_test.go +++ b/cd/main_test.go @@ -65,11 +65,13 @@ func TestRunPreviewGCP(t *testing.T) { } func testProviderPreview(t *testing.T, provider, accountId string) { - t.Helper() - - if err := exec.CommandContext(t.Context(), "make", "-C", "..", "install_defang-"+provider).Run(); err != nil { - t.Fatalf("failed to install defang-%s provider: %v", provider, err) - } + t.Run("install defang-"+provider, func(t *testing.T) { + makeCmd := exec.CommandContext(t.Context(), "make", "-C", "..", "install_defang-"+provider) + makeCmd.Stderr = t.Output() + if err := makeCmd.Run(); err != nil { + t.Fatalf("failed to install defang-%s provider: %v", provider, err) + } + }) eventsFile := t.TempDir() + "/events.json.gz" t.Setenv("DEFANG_EVENTS_UPLOAD_URL", "file://"+eventsFile) diff --git a/cd/testdata/preview-events-azure.json b/cd/testdata/preview-events-azure.json index e13e1c7e..69a5624b 100644 --- a/cd/testdata/preview-events-azure.json +++ b/cd/testdata/preview-events-azure.json @@ -38,7 +38,7 @@ "maybeCorrupt": false, "durationSeconds": 42, "resourceChanges": { - "create": 8 + "create": 10 }, "PolicyPacks": {}, "isPreview": true @@ -51,6 +51,121 @@ "cancelEvent": {}, "Error": null }, + { + "sequence": 42, + "timestamp": 42, + "resourcePreEvent": { + "metadata": { + "op": "create", + "urn": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:app:ManagedEnvironment$azure-native:monitor:DiagnosticSetting::cd-test-aca-logs", + "type": "azure-native:monitor:DiagnosticSetting", + "old": null, + "new": { + "type": "azure-native:monitor:DiagnosticSetting", + "urn": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:app:ManagedEnvironment$azure-native:monitor:DiagnosticSetting::cd-test-aca-logs", + "custom": true, + "id": "", + "parent": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:app:ManagedEnvironment::cd-test", + "inputs": { + "__createBeforeDelete": true, + "azureApiVersion": "2021-05-01-preview", + "logAnalyticsDestinationType": "Dedicated", + "logs": [ + { + "category": "ContainerAppConsoleLogs", + "enabled": true + }, + { + "category": "ContainerAppSystemLogs", + "enabled": true + } + ], + "name": "Defang-cd-test-azure-cd-test-aca-logs-***", + "resourceUri": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "workspaceId": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "outputs": {}, + "provider": "urn:pulumi:azure::cd-test::pulumi:providers:azure-native::azure::04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "detailedDiff": null, + "logical": true, + "provider": "urn:pulumi:azure::cd-test::pulumi:providers:azure-native::azure::04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "planning": true + }, + "Error": null + }, + { + "sequence": 42, + "timestamp": 42, + "resOutputsEvent": { + "metadata": { + "op": "create", + "urn": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:app:ManagedEnvironment$azure-native:monitor:DiagnosticSetting::cd-test-aca-logs", + "type": "azure-native:monitor:DiagnosticSetting", + "old": null, + "new": { + "type": "azure-native:monitor:DiagnosticSetting", + "urn": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:app:ManagedEnvironment$azure-native:monitor:DiagnosticSetting::cd-test-aca-logs", + "custom": true, + "id": "", + "parent": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:app:ManagedEnvironment::cd-test", + "inputs": { + "__createBeforeDelete": true, + "azureApiVersion": "2021-05-01-preview", + "logAnalyticsDestinationType": "Dedicated", + "logs": [ + { + "category": "ContainerAppConsoleLogs", + "enabled": true + }, + { + "category": "ContainerAppSystemLogs", + "enabled": true + } + ], + "name": "Defang-cd-test-azure-cd-test-aca-logs-***", + "resourceUri": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "workspaceId": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "outputs": { + "eventHubAuthorizationRuleId": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "eventHubName": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "id": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "logAnalyticsDestinationType": "Dedicated", + "logs": [ + { + "category": "ContainerAppConsoleLogs", + "categoryGroup": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "enabled": true, + "retentionPolicy": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + { + "category": "ContainerAppSystemLogs", + "categoryGroup": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "enabled": true, + "retentionPolicy": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" + } + ], + "marketplacePartnerId": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "metrics": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "name": "Defang-cd-test-azure-cd-test-aca-logs-***", + "serviceBusRuleId": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "storageAccountId": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "systemData": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "type": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "workspaceId": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "provider": "urn:pulumi:azure::cd-test::pulumi:providers:azure-native::azure::04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "detailedDiff": null, + "logical": true, + "provider": "urn:pulumi:azure::cd-test::pulumi:providers:azure-native::azure::04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "planning": true + }, + "Error": null + }, { "sequence": 42, "timestamp": 42, @@ -69,11 +184,7 @@ "inputs": { "__createBeforeDelete": true, "appLogsConfiguration": { - "destination": "log-analytics", - "logAnalyticsConfiguration": { - "customerId": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", - "sharedKey": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" - } + "destination": "azure-monitor" }, "azureApiVersion": "2025-02-02-preview", "environmentName": "Defang-cd-test-azure-***", @@ -115,11 +226,7 @@ "inputs": { "__createBeforeDelete": true, "appLogsConfiguration": { - "destination": "log-analytics", - "logAnalyticsConfiguration": { - "customerId": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", - "sharedKey": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" - } + "destination": "azure-monitor" }, "azureApiVersion": "2025-02-02-preview", "environmentName": "Defang-cd-test-azure-***", @@ -135,11 +242,8 @@ "outputs": { "appInsightsConfiguration": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", "appLogsConfiguration": { - "destination": "log-analytics", - "logAnalyticsConfiguration": { - "customerId": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", - "dynamicJsonColumns": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" - } + "destination": "azure-monitor", + "logAnalyticsConfiguration": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" }, "availabilityZones": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", "customDomainConfiguration": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", @@ -188,6 +292,89 @@ }, "Error": null }, + { + "sequence": 42, + "timestamp": 42, + "resourcePreEvent": { + "metadata": { + "op": "create", + "urn": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:operationalinsights:Workspace$azure-native:operationalinsights:Table::cd-test-console-logs", + "type": "azure-native:operationalinsights:Table", + "old": null, + "new": { + "type": "azure-native:operationalinsights:Table", + "urn": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:operationalinsights:Workspace$azure-native:operationalinsights:Table::cd-test-console-logs", + "custom": true, + "id": "", + "parent": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:operationalinsights:Workspace::cd-test", + "inputs": { + "azureApiVersion": "2023-09-01", + "plan": "Basic", + "resourceGroupName": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "tableName": "ContainerAppConsoleLogs", + "workspaceName": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "outputs": {}, + "provider": "urn:pulumi:azure::cd-test::pulumi:providers:azure-native::azure::04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "detailedDiff": null, + "logical": true, + "provider": "urn:pulumi:azure::cd-test::pulumi:providers:azure-native::azure::04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "planning": true + }, + "Error": null + }, + { + "sequence": 42, + "timestamp": 42, + "resOutputsEvent": { + "metadata": { + "op": "create", + "urn": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:operationalinsights:Workspace$azure-native:operationalinsights:Table::cd-test-console-logs", + "type": "azure-native:operationalinsights:Table", + "old": null, + "new": { + "type": "azure-native:operationalinsights:Table", + "urn": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:operationalinsights:Workspace$azure-native:operationalinsights:Table::cd-test-console-logs", + "custom": true, + "id": "", + "parent": "urn:pulumi:azure::cd-test::defang-azure:index:Project$azure-native:operationalinsights:Workspace::cd-test", + "inputs": { + "azureApiVersion": "2023-09-01", + "plan": "Basic", + "resourceGroupName": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "tableName": "ContainerAppConsoleLogs", + "workspaceName": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "outputs": { + "archiveRetentionInDays": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "id": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "lastPlanModifiedDate": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "name": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "plan": "Basic", + "provisioningState": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "restoredLogs": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "resultStatistics": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "retentionInDays": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "retentionInDaysAsDefault": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "schema": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "searchResults": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "systemData": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "totalRetentionInDays": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "totalRetentionInDaysAsDefault": "04da6b54-80e4-46f7-96ec-b56ff0331ba9", + "type": "04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "provider": "urn:pulumi:azure::cd-test::pulumi:providers:azure-native::azure::04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "detailedDiff": null, + "logical": true, + "provider": "urn:pulumi:azure::cd-test::pulumi:providers:azure-native::azure::04da6b54-80e4-46f7-96ec-b56ff0331ba9" + }, + "planning": true + }, + "Error": null + }, { "sequence": 42, "timestamp": 42, diff --git a/go.mod b/go.mod index f4a493be..1b2b07c8 100644 --- a/go.mod +++ b/go.mod @@ -23,16 +23,17 @@ require ( github.com/pulumi/pulumi-awsx/sdk/v3 v3.1.0 github.com/pulumi/pulumi-azure-native-sdk/app/v3 v3.17.0 github.com/pulumi/pulumi-azure-native-sdk/authorization/v3 v3.17.0 - github.com/pulumi/pulumi-azure-native-sdk/cognitiveservices/v3 v3.16.0 - github.com/pulumi/pulumi-azure-native-sdk/containerregistry/v3 v3.16.0 - github.com/pulumi/pulumi-azure-native-sdk/dbforpostgresql/v3 v3.16.0 + github.com/pulumi/pulumi-azure-native-sdk/cognitiveservices/v3 v3.17.0 + github.com/pulumi/pulumi-azure-native-sdk/containerregistry/v3 v3.17.0 + github.com/pulumi/pulumi-azure-native-sdk/dbforpostgresql/v3 v3.17.0 github.com/pulumi/pulumi-azure-native-sdk/keyvault/v3 v3.17.0 - github.com/pulumi/pulumi-azure-native-sdk/managedidentity/v3 v3.16.0 - github.com/pulumi/pulumi-azure-native-sdk/network/v3 v3.16.0 - github.com/pulumi/pulumi-azure-native-sdk/operationalinsights/v3 v3.16.0 - github.com/pulumi/pulumi-azure-native-sdk/privatedns/v3 v3.16.0 - github.com/pulumi/pulumi-azure-native-sdk/redisenterprise/v3 v3.16.0 - github.com/pulumi/pulumi-azure-native-sdk/resources/v3 v3.16.0 + github.com/pulumi/pulumi-azure-native-sdk/managedidentity/v3 v3.17.0 + github.com/pulumi/pulumi-azure-native-sdk/monitor/v3 v3.17.0 + github.com/pulumi/pulumi-azure-native-sdk/network/v3 v3.17.0 + github.com/pulumi/pulumi-azure-native-sdk/operationalinsights/v3 v3.17.0 + github.com/pulumi/pulumi-azure-native-sdk/privatedns/v3 v3.17.0 + github.com/pulumi/pulumi-azure-native-sdk/redisenterprise/v3 v3.17.0 + github.com/pulumi/pulumi-azure-native-sdk/resources/v3 v3.17.0 github.com/pulumi/pulumi-azure-native-sdk/v3 v3.17.0 github.com/pulumi/pulumi-gcp/sdk/v9 v9.21.0 github.com/pulumi/pulumi-go-provider v1.3.1 diff --git a/go.sum b/go.sum index 350da662..48caa0e1 100644 --- a/go.sum +++ b/go.sum @@ -502,26 +502,28 @@ github.com/pulumi/pulumi-azure-native-sdk/app/v3 v3.17.0 h1:QZksspyGhUliOncXYSun github.com/pulumi/pulumi-azure-native-sdk/app/v3 v3.17.0/go.mod h1:A4c9UObJvoBe0GZLalGGCf3x4WJsutLuZTgHGB9Du1A= github.com/pulumi/pulumi-azure-native-sdk/authorization/v3 v3.17.0 h1:XQ4akM+v4jT6bUDrbzqty0YpwPJAbS/47QzfuAt6+MM= github.com/pulumi/pulumi-azure-native-sdk/authorization/v3 v3.17.0/go.mod h1:eCpJILleDDKZkpjXQU1pRYOIinx/FfbCdNCiolUQRBM= -github.com/pulumi/pulumi-azure-native-sdk/cognitiveservices/v3 v3.16.0 h1:8qWHknbi8uL8YNEk4xZJCTB7j3WZNYgortFw88MJR2g= -github.com/pulumi/pulumi-azure-native-sdk/cognitiveservices/v3 v3.16.0/go.mod h1:kXMeD/KGfQcf6sHfFampUpa8bE4fpE14muA1parC3U0= -github.com/pulumi/pulumi-azure-native-sdk/containerregistry/v3 v3.16.0 h1:FH5Me4ZjzozVlmtqatPhUpUZB7vGJkGWvqk63qu6iCY= -github.com/pulumi/pulumi-azure-native-sdk/containerregistry/v3 v3.16.0/go.mod h1:E9QYEfEfcPlj7BC0j6n8QV7LnURip1pwpQCKGmYGB54= -github.com/pulumi/pulumi-azure-native-sdk/dbforpostgresql/v3 v3.16.0 h1:0ahdGJXgSOI/zcTLHsoxLyJoDhhgT7m39DqDjFWfAxQ= -github.com/pulumi/pulumi-azure-native-sdk/dbforpostgresql/v3 v3.16.0/go.mod h1:JMfQ+jmQf0YYI31s3fQe5hJ73hWEv0Mlc/sjukf6o8U= +github.com/pulumi/pulumi-azure-native-sdk/cognitiveservices/v3 v3.17.0 h1:VEnTJGvX3JxNpGCFG3Ebu36Dy80Y29CE/MhHdQ+VWiA= +github.com/pulumi/pulumi-azure-native-sdk/cognitiveservices/v3 v3.17.0/go.mod h1:9dmHyxXmeX8bniNWfP/+QEAcDPpmROxP+yMdZP8jlkE= +github.com/pulumi/pulumi-azure-native-sdk/containerregistry/v3 v3.17.0 h1:SHj85MVhfFwJDr9Sf86iHlAviRVW0oN8xqp6JVh0PNE= +github.com/pulumi/pulumi-azure-native-sdk/containerregistry/v3 v3.17.0/go.mod h1:7tEdr2jw1VMF22IYIEIdFezvHat5M9X9O9tJJUL5Sms= +github.com/pulumi/pulumi-azure-native-sdk/dbforpostgresql/v3 v3.17.0 h1:Uw0X84n9Iv0/eynA16rVNrZDz6W6QeWYw7unj4bgGS0= +github.com/pulumi/pulumi-azure-native-sdk/dbforpostgresql/v3 v3.17.0/go.mod h1:guBNNa6P2h8lz+RRzd4g6C5zeIJWdhpYgOEPJ1x9fYk= github.com/pulumi/pulumi-azure-native-sdk/keyvault/v3 v3.17.0 h1:M0Wkrkh9jqgGmMWuLGaHvB2mo/SwZcTaifGWuvnuYNo= github.com/pulumi/pulumi-azure-native-sdk/keyvault/v3 v3.17.0/go.mod h1:JuLBlQN5TH2BBNH7cZnixMouv/zlIgiUHmi21Yfxnxk= -github.com/pulumi/pulumi-azure-native-sdk/managedidentity/v3 v3.16.0 h1:uhCgqKSaOU3rkjUkzsDz0TbU50XSSygVQUX2/6+VWhc= -github.com/pulumi/pulumi-azure-native-sdk/managedidentity/v3 v3.16.0/go.mod h1:dHaprf7wwcp8Y/L3mGW8u2geqeaYQybjn9cScB2+yLo= -github.com/pulumi/pulumi-azure-native-sdk/network/v3 v3.16.0 h1:EXdiCzZNHpNc4gSem7e6VVpI/CrF2O8JdQcNFQus1tI= -github.com/pulumi/pulumi-azure-native-sdk/network/v3 v3.16.0/go.mod h1:2r+Vt14MLHpCr2bz/aXO6+VIGOl9dHXncqCoGsUsQUI= -github.com/pulumi/pulumi-azure-native-sdk/operationalinsights/v3 v3.16.0 h1:CbMcj7hGu6lMITRoxMGzg/q9E+SwuQ/YNaIKfhy9H74= -github.com/pulumi/pulumi-azure-native-sdk/operationalinsights/v3 v3.16.0/go.mod h1:52/CGRbaIlvVmyBWk70PD5ycrR5Pfb9LsWlp35RC4b4= -github.com/pulumi/pulumi-azure-native-sdk/privatedns/v3 v3.16.0 h1:4fknGY+uY24B8Y/xwL6ZutfwPbkq0xxnHOSbvreOKLM= -github.com/pulumi/pulumi-azure-native-sdk/privatedns/v3 v3.16.0/go.mod h1:Vip24OK8gb+niNLUsdu0+nAfm1QeUJJJTDjbMqvmIXQ= -github.com/pulumi/pulumi-azure-native-sdk/redisenterprise/v3 v3.16.0 h1:3r+4pH9TiiyIL/q//VHNLN/JRP0SUbIjK95ax0SqkJk= -github.com/pulumi/pulumi-azure-native-sdk/redisenterprise/v3 v3.16.0/go.mod h1:SVaFc/qU0xWfcS0u2bbgfWvy7aLWVLar3axkDj9hMQE= -github.com/pulumi/pulumi-azure-native-sdk/resources/v3 v3.16.0 h1:AP62GJ3I5a5tY31fEdPPBWL+uJ5T/Lh93iicOMzG2LM= -github.com/pulumi/pulumi-azure-native-sdk/resources/v3 v3.16.0/go.mod h1:aAh6uR3aOX3DqWcTYRxyxotIW5RT3S4iDJfpmjRtEdg= +github.com/pulumi/pulumi-azure-native-sdk/managedidentity/v3 v3.17.0 h1:y23mRd+p9ecVDuIqvsIp7qeFWu/QzSPwLL0Xdr9JjOo= +github.com/pulumi/pulumi-azure-native-sdk/managedidentity/v3 v3.17.0/go.mod h1:NLzoWbC35Yo7Dhzb3kAiUHiopOWB+2DZSeaZB3543dM= +github.com/pulumi/pulumi-azure-native-sdk/monitor/v3 v3.17.0 h1:gPaYOWWX5jQaX/gXYXDc29o4OscVgRF8CsOJzfWGvv8= +github.com/pulumi/pulumi-azure-native-sdk/monitor/v3 v3.17.0/go.mod h1:9C6U67A+YIC34iYbqVzA1emY/lPhNlcBC4BOAoZRG6o= +github.com/pulumi/pulumi-azure-native-sdk/network/v3 v3.17.0 h1:fW7bsFBqB4sEymCIRFYAad52h43UnPRzIaOnBtjW68Y= +github.com/pulumi/pulumi-azure-native-sdk/network/v3 v3.17.0/go.mod h1:R1uNYW2OcQQQUfPrOzHawd5+uREs/Kbo8YI6dUE4ePw= +github.com/pulumi/pulumi-azure-native-sdk/operationalinsights/v3 v3.17.0 h1:3vaKvNFXyr4zLnWfu+7QAnaxzWRXd5i8HkWU75fSUfs= +github.com/pulumi/pulumi-azure-native-sdk/operationalinsights/v3 v3.17.0/go.mod h1:+enwzyPuBJGAxBc6LNrURyETbF6QW8vKTrf8baBZsrQ= +github.com/pulumi/pulumi-azure-native-sdk/privatedns/v3 v3.17.0 h1:knhi0mQUnOjgEd2/1u8ntAco4iLUDjepyRsNj9ZwV7g= +github.com/pulumi/pulumi-azure-native-sdk/privatedns/v3 v3.17.0/go.mod h1:hxOs0SC2IzJeFrgnhR8u7Y8hp//Ak3uxHQQbWO57sHg= +github.com/pulumi/pulumi-azure-native-sdk/redisenterprise/v3 v3.17.0 h1:PpRRoEgQ/Iohhgsf1wkzF2GGFdSOuqO/xqoffubrvvo= +github.com/pulumi/pulumi-azure-native-sdk/redisenterprise/v3 v3.17.0/go.mod h1:RHwInC2f7J513R/EVgR0tWJEHpLF8mDqzy40I9pnCBg= +github.com/pulumi/pulumi-azure-native-sdk/resources/v3 v3.17.0 h1:38imOkVu0gkY5pZHDHXqstaOM2wtvWLFySANjAFiMgI= +github.com/pulumi/pulumi-azure-native-sdk/resources/v3 v3.17.0/go.mod h1:V0IgkHY2W+q5oolL6Kf4Amh13Rq3J68pzCPcqrtFJao= github.com/pulumi/pulumi-azure-native-sdk/v3 v3.17.0 h1:CFtP/hsyGR2jSAm/Fz+4QW8d/Slw619gUoLuobnCCX8= github.com/pulumi/pulumi-azure-native-sdk/v3 v3.17.0/go.mod h1:ELaNq3/fmYWdM6Y4vTQmheO9gGkeCrAMeiOD1XReDwA= github.com/pulumi/pulumi-docker-build/sdk/go/dockerbuild v0.0.3 h1:NxCXxRvzhUJP9dIvlpNlZKt/A3NHu3i9pC5XO+i8bR0= diff --git a/provider/defangazure/azure/acr.go b/provider/defangazure/azure/acr.go index ffe55edb..f1854379 100644 --- a/provider/defangazure/azure/acr.go +++ b/provider/defangazure/azure/acr.go @@ -104,24 +104,10 @@ func createACRTask( ctx *pulumi.Context, serviceName string, encodedYAML string, - contextURL pulumi.StringInput, registry *containerregistry.Registry, infra *SharedInfra, opts ...pulumi.ResourceOption, ) (*containerregistry.Task, error) { - // Log context URL for debugging (without exposing the token value). - contextURL.ToStringOutput().ApplyT(func(s string) string { - if idx := strings.Index(s, "?"); idx >= 0 { - base := s[:idx] - msg := fmt.Sprintf("ACR task %s: build context URL: %s (SAS token present, %d bytes)", - serviceName, base, len(s)-idx-1) - _ = ctx.Log.Info(msg, nil) - } else { - _ = ctx.Log.Info(fmt.Sprintf("ACR task %s: build context URL: %s (no SAS token)", serviceName, s), nil) - } - return s - }) - task, err := containerregistry.NewTask(ctx, serviceName, &containerregistry.TaskArgs{ ResourceGroupName: infra.ResourceGroup.Name, RegistryName: registry.Name, diff --git a/provider/defangazure/azure/dns.go b/provider/defangazure/azure/dns.go index 3e0c0e1e..aa119166 100644 --- a/provider/defangazure/azure/dns.go +++ b/provider/defangazure/azure/dns.go @@ -57,7 +57,7 @@ func CreateDNSZones( Location: pulumi.String("global"), RegistrationEnabled: pulumi.Bool(false), VirtualNetwork: &privatedns.SubResourceArgs{Id: networking.VNet.ID().ToStringOutput()}, - }, append(opts, pulumi.Parent(pgZone))...) + }, opts...) if err != nil { return nil, fmt.Errorf("creating postgres DNS VNet link: %w", err) } @@ -86,7 +86,7 @@ func CreateDNSZones( Location: pulumi.String("global"), RegistrationEnabled: pulumi.Bool(false), VirtualNetwork: &privatedns.SubResourceArgs{Id: networking.VNet.ID().ToStringOutput()}, - }, append(opts, pulumi.Parent(redisZone))...) + }, opts...) if err != nil { return nil, fmt.Errorf("creating Redis DNS VNet link: %w", err) } diff --git a/provider/defangazure/azure/image.go b/provider/defangazure/azure/image.go index 56019ea5..9da2ae2b 100644 --- a/provider/defangazure/azure/image.go +++ b/provider/defangazure/azure/image.go @@ -173,7 +173,6 @@ func buildServiceImage( ctx, serviceName, encodedYAML, - svc.Build.Context, infra.registry, sharedInfra, opts..., diff --git a/provider/defangazure/azure/llm.go b/provider/defangazure/azure/llm.go index 6bfa8bf7..c017e9e5 100644 --- a/provider/defangazure/azure/llm.go +++ b/provider/defangazure/azure/llm.go @@ -216,7 +216,7 @@ func CreateLLMDeployment( Name: modelSKU, Capacity: pulumi.Int(1), }, - }, append(opts, pulumi.Parent(llmInfra.Account))...) + }, opts...) if err != nil { return fmt.Errorf("creating Azure AI Foundry deployment %s: %w", deploymentName, err) } @@ -342,7 +342,7 @@ func createLLMPrivateEndpoint( PrivateDnsZoneId: openaiZone.ID().ToStringOutput(), }, }, - }, append(opts, pulumi.Parent(pe))...); err != nil { + }, opts...); err != nil { return fmt.Errorf("creating LLM private DNS zone group: %w", err) } return nil diff --git a/provider/defangazure/azure/postgres.go b/provider/defangazure/azure/postgres.go index ae703fa8..a383072f 100644 --- a/provider/defangazure/azure/postgres.go +++ b/provider/defangazure/azure/postgres.go @@ -168,8 +168,6 @@ func CreatePostgresFlexible( return nil, fmt.Errorf("creating PostgreSQL Flexible Server: %w", err) } - serverChildOpts := append([]pulumi.ResourceOption{pulumi.Parent(server)}, opts...) - // Allowlist extensions. Azure Postgres Flexible Server blocks CREATE EXTENSION // unless the extension is listed in the azure.extensions server parameter first. // This list mirrors what AWS RDS and GCP Cloud SQL permit by default, restricted @@ -191,7 +189,7 @@ func CreatePostgresFlexible( "TEMPORAL_TABLES,TSM_SYSTEM_ROWS,TSM_SYSTEM_TIME,UNACCENT,UUID-OSSP,VECTOR", ), Source: pulumi.String("user-override"), - }, serverChildOpts...) + }, opts...) if err != nil { return nil, fmt.Errorf("enabling extensions: %w", err) } @@ -203,7 +201,7 @@ func CreatePostgresFlexible( // // Azure serializes server-parameter changes — applying two Configurations in // parallel yields `ServerIsBusy` on the loser. Sequence this after extensions. - noTlsOpts := append([]pulumi.ResourceOption{pulumi.DependsOn([]pulumi.Resource{extensionsCfg})}, serverChildOpts...) + noTlsOpts := append([]pulumi.ResourceOption{pulumi.DependsOn([]pulumi.Resource{extensionsCfg})}, opts...) noTlsCfg, err := dbforpostgresql.NewConfiguration(ctx, "no-tls", &dbforpostgresql.ConfigurationArgs{ ResourceGroupName: infra.ResourceGroup.Name, ServerName: server.Name, @@ -221,7 +219,7 @@ func CreatePostgresFlexible( ResourceGroupName: infra.ResourceGroup.Name, ServerName: server.Name, DatabaseName: pg.DBName, - }, serverChildOpts...) + }, opts...) if err != nil { return nil, fmt.Errorf("creating PostgreSQL database: %w", err) } @@ -235,7 +233,7 @@ func CreatePostgresFlexible( ServerName: server.Name, StartIpAddress: pulumi.String("0.0.0.0"), EndIpAddress: pulumi.String("0.0.0.0"), - }, serverChildOpts...) + }, opts...) if err != nil { return nil, fmt.Errorf("creating PostgreSQL firewall rule: %w", err) } diff --git a/provider/defangazure/azure/recipe.go b/provider/defangazure/azure/recipe.go index 4c0ee699..a839e167 100644 --- a/provider/defangazure/azure/recipe.go +++ b/provider/defangazure/azure/recipe.go @@ -4,16 +4,22 @@ import "github.com/DefangLabs/pulumi-defang/provider/common" // Azure recipe config accessors. Each reads from defang: in stack config. var ( - BackupRetentionDays = common.Int("backup-retention-days", 7) - DeletionProtection = common.DeletionProtection - GeoRedundantBackup = common.Bool("geo-redundant-backup", false) - HighAvailability = common.Bool("high-availability", false) - LogWorkspaceSku = common.String("log-workspace-sku", "PerGB2018") + BackupRetentionDays = common.Int("backup-retention-days", 7) + DeletionProtection = common.DeletionProtection + GeoRedundantBackup = common.Bool("geo-redundant-backup", false) + HighAvailability = common.Bool("high-availability", false) + // LogConsoleLogsPlan controls the table plan for ContainerAppConsoleLogs. + // Default "Basic" (~$0.50/GB ingest, 8-day retention, per-query scan cost, + // no log alerts) — covers `defang logs` style live browsing of stdout. + // HA override: "Analytics" (~$2.30/GB, full retention + alerts + KQL). + // "Auxiliary" (~$0.13/GB) is also accepted; loses most query power. + LogConsoleLogsPlan = common.String("log-console-logs-plan", "Basic") // LogWorkspaceDailyQuotaGb caps daily ingestion in GB. 0 = no cap. // Default 1 GB/day = ~30 GB/mo, ~$70 ceiling on PerGB2018 (~$2.30/GB). // Chatty workloads (AI agents) override upward; an unbounded default // has been seen to bill >$700/mo against a single workspace. - LogWorkspaceDailyQuotaGb = common.Int("log-workspace-daily-quota-gb", 1) + LogWorkspaceDailyQuotaGb = common.Int("log-workspace-daily-quota-gb", 1) + LogWorkspaceSku = common.String("log-workspace-sku", "PerGB2018") MaxReplicas = common.Int("max-replicas", 0) PostgresTier = common.String("postgres-tier", "burstable") PostgresStorageSizeGB = common.Int("storage-size-gb", 32) diff --git a/provider/defangazure/azure/redis.go b/provider/defangazure/azure/redis.go index a5bc9fc2..61b406ea 100644 --- a/provider/defangazure/azure/redis.go +++ b/provider/defangazure/azure/redis.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" + "github.com/DefangLabs/pulumi-defang/provider/common" "github.com/DefangLabs/pulumi-defang/provider/compose" "github.com/pulumi/pulumi-azure-native-sdk/network/v3" redis "github.com/pulumi/pulumi-azure-native-sdk/redisenterprise/v3" @@ -119,8 +120,7 @@ func CreateRedisEnterprise( ClientProtocol: pulumi.String(clientProtocol), ClusteringPolicy: pulumi.String("EnterpriseCluster"), Port: pulumi.Int(10000), - }, append(opts, - pulumi.Parent(cluster), + }, common.MergeOptions(opts, pulumi.ReplaceOnChanges([]string{"clusteringPolicy", "clientProtocol"}), pulumi.DeleteBeforeReplace(true), )...) diff --git a/provider/defangazure/project.go b/provider/defangazure/project.go index aefa2a31..1fa101ee 100644 --- a/provider/defangazure/project.go +++ b/provider/defangazure/project.go @@ -10,6 +10,7 @@ import ( "github.com/DefangLabs/pulumi-defang/provider/compose" providerazure "github.com/DefangLabs/pulumi-defang/provider/defangazure/azure" "github.com/pulumi/pulumi-azure-native-sdk/app/v3" + "github.com/pulumi/pulumi-azure-native-sdk/monitor/v3" "github.com/pulumi/pulumi-azure-native-sdk/operationalinsights/v3" "github.com/pulumi/pulumi-azure-native-sdk/resources/v3" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" @@ -319,20 +320,22 @@ func createManagedEnvironment( if err != nil { return nil, fmt.Errorf("creating Log Analytics workspace: %w", err) } - logKeys := operationalinsights.GetSharedKeysOutput(ctx, operationalinsights.GetSharedKeysOutputArgs{ - ResourceGroupName: infra.ResourceGroup.Name, - WorkspaceName: logWorkspace.Name, - }, parentOpt) + // "azure-monitor" routes through Azure Monitor + a DiagnosticSetting (below), + // which lands ACA logs in the modern, DCR-based ContainerAppConsoleLogs / + // ContainerAppSystemLogs tables. The earlier "log-analytics" destination + // used the workspace shared-key API and wrote to Classic Custom Log + // ContainerAppConsoleLogs_CL tables — those don't support Basic plan + // (Azure: "Basic Logs plan is not supported by CustomLog Classic tables"), + // so workspace ingest stayed locked to Analytics ~$2.30/GB. The + // DiagnosticSetting path unlocks the Basic plan ~$0.50/GB on the modern + // tables. AppLogsConfiguration must omit LogAnalyticsConfiguration when + // Destination is azure-monitor — the field is only valid with log-analytics. envArgs := &app.ManagedEnvironmentArgs{ ResourceGroupName: infra.ResourceGroup.Name, // Location: pulumi.String(location), AppLogsConfiguration: &app.AppLogsConfigurationArgs{ - Destination: pulumi.String("log-analytics"), - LogAnalyticsConfiguration: &app.LogAnalyticsConfigurationArgs{ - CustomerId: logWorkspace.CustomerId, - SharedKey: logKeys.PrimarySharedKey(), - }, + Destination: pulumi.String("azure-monitor"), }, } if infra.Networking != nil { @@ -347,6 +350,67 @@ func createManagedEnvironment( if err != nil { return nil, fmt.Errorf("creating managed environment: %w", err) } + + // ACA log category names. In LogAnalyticsDestinationType=Dedicated mode + // the category name doubles as the destination Log Analytics table name, + // so we reuse the same constants below for the DiagnosticSetting category + // and the Table.TableName / import ID. + const ( + consoleLogsTable = "ContainerAppConsoleLogs" + systemLogsTable = "ContainerAppSystemLogs" + ) + + // Route ACA's two log categories from the env (via Azure Monitor) into the + // workspace, landing in the modern DCR-based tables (Basic-plan eligible). + // LogAnalyticsDestinationType="Dedicated" forces per-resource-type tables; + // default (null/AzureDiagnostics) would merge everything into the generic + // AzureDiagnostics table and bypass the schema the CLI expects. + // Use monitor/v3 (not insights/v1). In azure-native v3 the resource was + // renamed insights → monitor; the v3 plugin only knows the new token + // "azure-native:monitor:DiagnosticSetting" as a creatable resource and + // keeps "azure-native:insights:DiagnosticSetting" as an alias for state + // migration only. Calling NewDiagnosticSetting via the legacy insights/v1 + // SDK registers with the old token and fails with "Resource type … not + // found", regardless of any pulumi.Version pin. + diagSetting, err := monitor.NewDiagnosticSetting(ctx, name+"-aca-logs", &monitor.DiagnosticSettingArgs{ + ResourceUri: env.ID().ToStringOutput(), + WorkspaceId: logWorkspace.ID().ToStringPtrOutput(), + LogAnalyticsDestinationType: pulumi.String("Dedicated"), + Logs: monitor.LogSettingsArray{ + &monitor.LogSettingsArgs{Category: pulumi.String(consoleLogsTable), Enabled: pulumi.Bool(true)}, + &monitor.LogSettingsArgs{Category: pulumi.String(systemLogsTable), Enabled: pulumi.Bool(true)}, + }, + }, parentOpt, pulumi.Parent(env)) + if err != nil { + return nil, fmt.Errorf("creating ACA diagnostic setting: %w", err) + } + + // Pin the plan on the console logs table (Container Apps' stdout sink). + // The table schema isn't a true workspace built-in — it's registered by + // the Container Apps Monitor solution, which attaches when an env links + // the workspace as its log-analytics destination. So we must wait for + // `env` before the table is queryable (or its ID resolvable for Import). + // Plain Create would race with the solution registration and fail with + // "cannot create already existing resource"; Import + DependsOn(env) + // guarantees the schema exists, then applies the Plan diff. + consoleLogsPlan := providerazure.LogConsoleLogsPlan.Get(ctx) + consoleLogsImportID := logWorkspace.ID().ToStringOutput().ApplyT(func(id string) pulumi.ID { + return pulumi.ID(id + "/tables/" + consoleLogsTable) + }).(pulumi.IDOutput) + if _, err := operationalinsights.NewTable(ctx, name+"-console-logs", &operationalinsights.TableArgs{ + ResourceGroupName: infra.ResourceGroup.Name, + WorkspaceName: logWorkspace.Name, + TableName: pulumi.String(consoleLogsTable), + Plan: pulumi.String(consoleLogsPlan), + }, + parentOpt, + pulumi.Parent(logWorkspace), + pulumi.DependsOn([]pulumi.Resource{diagSetting}), + pulumi.Import(consoleLogsImportID), + ); err != nil { + return nil, fmt.Errorf("setting %s plan on %s: %w", consoleLogsPlan, consoleLogsTable, err) + } + return env, nil }