diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index fb1f185dc..417d7da3b 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -62,7 +62,7 @@ jobs: - name: Check nix-shell default.nix run: | set -o pipefail - nix-shell --pure -E 'with import {}; mkShell { buildInputs = [ (import ./default.nix {}) ]; }' --run defang 2>&1 | sed -u 's|\s\+got:|::error file=pkgs/defang/cli.nix,line=9::Replace the vendorHash in cli.nix with the correct value:|' + nix-shell --pure -E 'with import {}; mkShell { buildInputs = [ (import ./default.nix {}) ]; }' --run defang 2>&1 | sed -u 's|\s\+got:|::error file=pkgs/defang/cli.nix,line=10::Replace the vendorHash in cli.nix with the correct value:|' # go-byoc-test: # runs-on: ubuntu-latest @@ -321,7 +321,7 @@ jobs: push-docker: runs-on: ubuntu-latest needs: - - go-release + - go-release steps: - uses: actions/checkout@v4 diff --git a/defang.code-workspace b/defang.code-workspace index 0c81507e6..72d3f4942 100644 --- a/defang.code-workspace +++ b/defang.code-workspace @@ -1,19 +1,19 @@ { - "folders": [ - { - "path": "." - }, - { - "path": "src" - } - ], - "settings": { - "go.testEnvVars": { - "AWS_PROFILE": "defang-sandbox" - }, - "go.buildTags": "integration", - "go.testFlags": ["-short"], - "go.testTimeout": "300s", - "makefile.configureOnOpen": false - } -} \ No newline at end of file + "folders": [ + { + "path": "." + }, + { + "path": "src" + } + ], + "settings": { + "go.testEnvVars": { + "AWS_PROFILE": "defang-sandbox" + }, + "go.buildTags": "integration", + "go.testFlags": ["-short", "-v"], + "go.testTimeout": "300s", + "makefile.configureOnOpen": false + } +} diff --git a/flake.nix b/flake.nix index 6327289d8..8f0c2dfc0 100644 --- a/flake.nix +++ b/flake.nix @@ -18,6 +18,7 @@ mkShell { buildInputs = [ + azure-cli buf crane git diff --git a/pkgs/defang/cli.nix b/pkgs/defang/cli.nix index 70450635c..348434303 100644 --- a/pkgs/defang/cli.nix +++ b/pkgs/defang/cli.nix @@ -7,7 +7,7 @@ buildGoModule { pname = "defang-cli"; version = "git"; src = ../../src; - vendorHash = "sha256-4QMrneh4I2gTFf7erVnakqPDZakFzceGaN+ieAMNPX0="; # TODO: use fetchFromGitHub + vendorHash = "sha256-TiasfKgJyoxwl6B3uvTDFXI417WL8E1EYm/ljHLSFn4="; # TODO: use fetchFromGitHub subPackages = [ "cmd/cli" ]; diff --git a/src/go.mod b/src/go.mod index c74693378..999acfe65 100644 --- a/src/go.mod +++ b/src/go.mod @@ -16,6 +16,12 @@ require ( cloud.google.com/go/secretmanager v1.14.5 cloud.google.com/go/storage v1.50.0 github.com/AlecAivazis/survey/v2 v2.3.7 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerinstance/armcontainerinstance/v2 v2.4.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources/v2 v2.1.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/DefangLabs/secret-detector v0.0.0-20250108223530-c2b44d4c1f8f github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 github.com/aws/aws-sdk-go-v2 v1.32.6 @@ -35,7 +41,7 @@ require ( github.com/compose-spec/compose-go/v2 v2.7.2-0.20250715094302-8da9902241f9 github.com/digitalocean/godo v1.131.1 github.com/docker/docker v25.0.6+incompatible - github.com/golang-jwt/jwt/v5 v5.2.2 + github.com/golang-jwt/jwt/v5 v5.2.3 github.com/google/uuid v1.6.0 github.com/googleapis/gax-go/v2 v2.14.1 github.com/gorilla/websocket v1.5.0 @@ -51,10 +57,10 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.6 - golang.org/x/mod v0.18.0 + golang.org/x/mod v0.25.0 golang.org/x/oauth2 v0.29.0 - golang.org/x/sys v0.32.0 - golang.org/x/term v0.31.0 + golang.org/x/sys v0.34.0 + golang.org/x/term v0.33.0 google.golang.org/api v0.229.0 google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb google.golang.org/grpc v1.72.0 @@ -70,6 +76,8 @@ require ( cloud.google.com/go/compute/metadata v0.6.0 // indirect cloud.google.com/go/longrunning v0.6.6 // indirect cloud.google.com/go/monitoring v1.24.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0 // indirect @@ -91,12 +99,14 @@ require ( github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf // indirect + github.com/kylelemons/godebug v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.2 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect github.com/sergi/go-diff v1.3.1 // indirect @@ -109,8 +119,8 @@ require ( go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.37.0 // indirect - golang.org/x/net v0.39.0 // indirect + golang.org/x/crypto v0.40.0 // indirect + golang.org/x/net v0.42.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect gopkg.in/ini.v1 v1.66.2 // indirect @@ -136,7 +146,7 @@ require ( github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -150,13 +160,13 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/pkg/errors v0.9.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect - go.opentelemetry.io/otel v1.35.0 // indirect + go.opentelemetry.io/otel v1.37.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 // indirect - go.opentelemetry.io/otel/metric v1.35.0 // indirect + go.opentelemetry.io/otel/metric v1.37.0 // indirect go.opentelemetry.io/otel/sdk v1.35.0 // indirect - go.opentelemetry.io/otel/trace v1.35.0 // indirect - golang.org/x/sync v0.13.0 // indirect - golang.org/x/text v0.24.0 // indirect + go.opentelemetry.io/otel/trace v1.37.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/text v0.27.0 // indirect golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.22.0 // indirect + golang.org/x/tools v0.34.0 // indirect ) diff --git a/src/go.sum b/src/go.sum index fe6b07db6..39b3f1b1c 100644 --- a/src/go.sum +++ b/src/go.sum @@ -32,8 +32,34 @@ cloud.google.com/go/trace v1.11.3 h1:c+I4YFjxRQjvAhRmSsmjpASUKq88chOX854ied0K/pE cloud.google.com/go/trace v1.11.3/go.mod h1:pt7zCYiDSQjC9Y2oqCsh9jF4GStB/hmjrYLsxRR27q8= github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 h1:Hr5FTipp7SL07o2FvoVOX9HRiRH3CR3Mj8pxqCcdD5A= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2/go.mod h1:QyVsSSN64v5TGltphKLQ2sQxe4OBQg0J1eKRcVBnfgE= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerinstance/armcontainerinstance/v2 v2.4.0 h1:+dIXMjlifRbG3d01DF8dwckUSXADuW5dgBNt1fbkpv0= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerinstance/armcontainerinstance/v2 v2.4.0/go.mod h1:FN0UJ15tJ7kV7JYrYAleEq44Ew1cUiyLcJrfrTxHGd0= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0 h1:2qsIIvxVT+uE6yrNldntJKlLRgxGbZ85kgtz5SNBhMw= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0/go.mod h1:AW8VEadnhw9xox+VaVd9sP7NjzOAnaZBLRH6Tq3cJ38= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.2.0 h1:akP6VpxJGgQRpDR1P462piz/8OhYLRCreDj48AyNabc= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.2.0/go.mod h1:8wzvopPfyZYPaQUoKW87Zfdul7jmJMDfp/k7YY3oJyA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources/v2 v2.1.0 h1:seyVIpxalxYmfjoo8MB4rRzWaobMG+KJ2+MAUrEvDGU= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources/v2 v2.1.0/go.mod h1:M3QD7IyKZBaC4uAKjitTOSOXdcPC6JS1A9oOW3hYjbQ= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 h1:/Zt+cDPnpC3OVDm/JKLOs7M2DKmLRIIp3XIx9pHHiig= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1/go.mod h1:Ng3urmn6dYe8gnbCMoHHVl5APYz2txho3koEkV2o2HA= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 h1:FwladfywkNirM+FZYLBR2kBz5C8Tg0fw5w5Y7meRXWI= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2/go.mod h1:vv5Ad0RrIoT1lJFdWBZwt4mB1+j+V8DUroixmKDTCdk= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/DefangLabs/cobra v1.8.0-defang h1:rTzAg1XbEk3yXUmQPumcwkLgi8iNCby5CjyG3sCwzKk= github.com/DefangLabs/cobra v1.8.0-defang/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/DefangLabs/secret-detector v0.0.0-20250108223530-c2b44d4c1f8f h1:RTbUqLhPxejgK92ifVdMTIW9H23QLlscy8QXPDTfaL4= @@ -127,6 +153,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/digitalocean/godo v1.131.1 h1:2QsRwjNukKgOQbflMxOsTDoC05o5UKBpqQMFKXegYKE= github.com/digitalocean/godo v1.131.1/go.mod h1:PU8JB6I1XYkQIdHFop8lLAY9ojp6M0XcU0TWaQSxbrc= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= @@ -154,8 +182,8 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -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/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/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/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= @@ -166,8 +194,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= -github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= +github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -215,6 +243,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= +github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -224,6 +254,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mark3labs/mcp-go v0.21.0 h1:oyEtiXg8PnrVEFis9b1AwbiUWF2dTbyBP5yLo7SruXE= @@ -269,11 +301,13 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= +github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -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/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/ross96D/cancelreader v0.2.6 h1:XLPWassoMWRTlHvEoVKS3z0N0a7jHcIupGU0U1gNArw= github.com/ross96D/cancelreader v0.2.6/go.mod h1:sSs12d88ds2FFb9aOsKYyhTJCJDQDOll6gpyILZwIzc= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -311,22 +345,22 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= @@ -335,29 +369,29 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 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.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -370,18 +404,18 @@ 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.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 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.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= +golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= 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.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -389,8 +423,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -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/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/pkg/cli/client/byoc/aws/byoc.go b/src/pkg/cli/client/byoc/aws/byoc.go index 04515a892..9d87f8ec4 100644 --- a/src/pkg/cli/client/byoc/aws/byoc.go +++ b/src/pkg/cli/client/byoc/aws/byoc.go @@ -35,7 +35,6 @@ import ( s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" "github.com/aws/aws-sdk-go-v2/service/sts" "github.com/aws/smithy-go" - "github.com/aws/smithy-go/ptr" "github.com/bufbuild/connect-go" composeTypes "github.com/compose-spec/compose-go/v2/types" "google.golang.org/protobuf/proto" @@ -139,26 +138,24 @@ func (b *ByocAws) setUpCD(ctx context.Context) error { term.Debugf("Using CD image: %q", b.CDImage) - cdTaskName := byoc.CdTaskPrefix + cdContainerName := byoc.CdTaskPrefix containers := []types.Container{ { // FIXME: get the Pulumi image or version from Fabric: https://github.com/DefangLabs/defang/issues/1027 - Image: "public.ecr.aws/pulumi/pulumi-nodejs:" + b.PulumiVersion, - Name: ecs.CdContainerName, - Cpus: 2.0, - Memory: 2048_000_000, // 2G - Essential: ptr.Bool(true), + Image: "public.ecr.aws/pulumi/pulumi-nodejs:" + b.PulumiVersion, + Name: ecs.CdContainerName, + Cpus: 2.0, + Memory: 2048_000_000, // 2G VolumesFrom: []string{ - cdTaskName, + cdContainerName, }, WorkDir: "/app", - DependsOn: map[string]types.ContainerCondition{cdTaskName: "START"}, EntryPoint: []string{"node", "lib/index.js"}, }, { - Image: b.CDImage, - Name: cdTaskName, - Essential: ptr.Bool(false), + Image: b.CDImage, + Name: cdContainerName, + IsInit: true, Volumes: []types.TaskVolume{ { Source: "pulumi-plugins", @@ -375,6 +372,8 @@ func (b *ByocAws) bucketName() string { func (b *ByocAws) environment(projectName string) (map[string]string, error) { region := b.driver.Region // TODO: this should be the destination region, not the CD region; make customizable + + // From https://www.pulumi.com/docs/iac/concepts/state-and-backends/#aws-s3 defangStateUrl := fmt.Sprintf(`s3://%s?region=%s&awssdk=v2`, b.bucketName(), region) pulumiBackendKey, pulumiBackendValue, err := byoc.GetPulumiBackend(defangStateUrl) if err != nil { diff --git a/src/pkg/cli/client/byoc/azure/byoc.go b/src/pkg/cli/client/byoc/azure/byoc.go new file mode 100644 index 000000000..9af9e6fb7 --- /dev/null +++ b/src/pkg/cli/client/byoc/azure/byoc.go @@ -0,0 +1,228 @@ +package azure + +import ( + "context" + "encoding/base64" + "errors" + "fmt" + "os" + + "github.com/DefangLabs/defang/src/pkg" + "github.com/DefangLabs/defang/src/pkg/cli/client" + "github.com/DefangLabs/defang/src/pkg/cli/client/byoc" + "github.com/DefangLabs/defang/src/pkg/cli/compose" + "github.com/DefangLabs/defang/src/pkg/clouds/azure/aci" + "github.com/DefangLabs/defang/src/pkg/term" + "github.com/DefangLabs/defang/src/pkg/types" + defangv1 "github.com/DefangLabs/defang/src/protos/io/defang/v1" + "google.golang.org/protobuf/proto" +) + +type ByocAzure struct { + *byoc.ByocBaseClient + + driver *aci.ContainerInstance +} + +var _ client.Provider = (*ByocAzure)(nil) + +func NewByocProvider(ctx context.Context, tenantName types.TenantName) *ByocAzure { + b := &ByocAzure{ + driver: aci.NewContainerInstance("defang-cd", ""), // default location => from AZURE_LOCATION env var + } + b.ByocBaseClient = byoc.NewByocBaseClient(ctx, tenantName, b) + return b +} + +// AccountInfo implements client.Provider. +func (b *ByocAzure) AccountInfo(context.Context) (*client.AccountInfo, error) { + return &client.AccountInfo{ + AccountID: b.driver.SubscriptionID, + Provider: client.ProviderAzure, + Region: b.driver.Location.String(), + }, nil +} + +// BootstrapCommand implements client.Provider. +func (b *ByocAzure) BootstrapCommand(context.Context, client.BootstrapCommandRequest) (types.ETag, error) { + return "", errors.ErrUnsupported +} + +// BootstrapList implements client.Provider. +func (b *ByocAzure) BootstrapList(context.Context) ([]string, error) { + return nil, errors.ErrUnsupported +} + +// CreateUploadURL implements client.Provider. +func (b *ByocAzure) CreateUploadURL(ctx context.Context, req *defangv1.UploadURLRequest) (*defangv1.UploadURLResponse, error) { + if err := b.setUp(ctx); err != nil { + return nil, err + } + + url, err := b.driver.CreateUploadURL(ctx, req.Digest) + if err != nil { + return nil, err + } + + return &defangv1.UploadURLResponse{ + Url: url, + }, nil +} + +// Delete implements client.Provider. +func (b *ByocAzure) Delete(context.Context, *defangv1.DeleteRequest) (*defangv1.DeleteResponse, error) { + return nil, errors.ErrUnsupported +} + +// DeleteConfig implements client.Provider. +func (b *ByocAzure) DeleteConfig(context.Context, *defangv1.Secrets) error { + return errors.ErrUnsupported +} + +func (b *ByocAzure) setUp(ctx context.Context) error { + return b.driver.SetUp(ctx, []types.Container{ + { + Name: "defang-cd", + Image: b.CDImage, + }, + }) +} + +// Deploy implements client.Provider. +func (b *ByocAzure) Deploy(ctx context.Context, req *defangv1.DeployRequest) (*defangv1.DeployResponse, error) { + return b.deploy(ctx, req, "up") +} + +func (b *ByocAzure) deploy(ctx context.Context, req *defangv1.DeployRequest, verb string) (*defangv1.DeployResponse, error) { + // If multiple Compose files were provided, req.Compose is the merged representation of all the files + project, err := compose.LoadFromContent(ctx, req.Compose, "") + if err != nil { + return nil, err + } + + if err := b.setUp(ctx); err != nil { + return nil, err + } + + etag := pkg.RandomID() + serviceInfos, err := b.GetServiceInfos(ctx, project.Name, req.DelegateDomain, etag, project.Services) + if err != nil { + return nil, err + } + + data, err := proto.Marshal(&defangv1.ProjectUpdate{ + CdVersion: b.CDImage, + Compose: req.Compose, + Services: serviceInfos, + }) + if err != nil { + return nil, err + } + + // From https://www.pulumi.com/docs/iac/concepts/state-and-backends/#azure-blob-storage + defangStateUrl := fmt.Sprintf(`azblob://%s?storage_account=%s`, b.driver.BlobContainerName, b.driver.StorageAccount) + pulumiBackendKey, pulumiBackendValue, err := byoc.GetPulumiBackend(defangStateUrl) + if err != nil { + return nil, err + } + env := []string{ + "AZURE_LOCATION=" + b.driver.Location.String(), + "AZURE_SUBSCRIPTION_ID=" + b.driver.SubscriptionID, + "DEFANG_DEBUG=" + os.Getenv("DEFANG_DEBUG"), // TODO: use the global DoDebug flag + "DEFANG_JSON=" + os.Getenv("DEFANG_JSON"), + "DEFANG_ORG=" + b.TenantName, + "DEFANG_PREFIX=" + byoc.DefangPrefix, + "DEFANG_STATE_URL=" + defangStateUrl, + "NPM_CONFIG_UPDATE_NOTIFIER=" + "false", + // "PRIVATE_DOMAIN=" + byoc.GetPrivateDomain(projectName), TODO: implement + "PROJECT=" + project.Name, // may be empty + pulumiBackendKey + "=" + pulumiBackendValue, // TODO: make secret + "PULUMI_CONFIG_PASSPHRASE=" + byoc.PulumiConfigPassphrase, // TODO: make secret + "PULUMI_COPILOT=false", + "PULUMI_SKIP_UPDATE_CHECK=true", + "STACK=" + b.PulumiStack, + } + if !term.StdoutCanColor() { + env = append(env, "NO_COLOR=1") + } + err = byoc.DebugPulumi(ctx, env, verb, base64.StdEncoding.EncodeToString(data)) // TODO: handle large projects + return &defangv1.DeployResponse{Etag: etag, Services: serviceInfos}, err +} + +// Destroy implements client.Provider. +func (b *ByocAzure) Destroy(context.Context, *defangv1.DestroyRequest) (types.ETag, error) { + return "", errors.ErrUnsupported +} + +// GetDeploymentStatus implements client.Provider. +func (b *ByocAzure) GetDeploymentStatus(context.Context) error { + return errors.ErrUnsupported +} + +// GetProjectUpdate implements client.Provider. +func (b *ByocAzure) GetProjectUpdate(context.Context, string) (*defangv1.ProjectUpdate, error) { + return nil, errors.ErrUnsupported +} + +// GetService implements client.Provider. +func (b *ByocAzure) GetService(context.Context, *defangv1.GetRequest) (*defangv1.ServiceInfo, error) { + return nil, errors.ErrUnsupported +} + +// GetServices implements client.Provider. +func (b *ByocAzure) GetServices(context.Context, *defangv1.GetServicesRequest) (*defangv1.GetServicesResponse, error) { + return nil, errors.ErrUnsupported +} + +// ListConfig implements client.Provider. +func (b *ByocAzure) ListConfig(context.Context, *defangv1.ListConfigsRequest) (*defangv1.Secrets, error) { + // return nil, errors.ErrUnsupported + return &defangv1.Secrets{}, nil +} + +// PrepareDomainDelegation implements client.Provider. +func (b *ByocAzure) PrepareDomainDelegation(context.Context, client.PrepareDomainDelegationRequest) (*client.PrepareDomainDelegationResponse, error) { + return nil, nil // TODO: implement domain delegation for Azure +} + +// Preview implements client.Provider. +func (b *ByocAzure) Preview(ctx context.Context, req *defangv1.DeployRequest) (*defangv1.DeployResponse, error) { + return b.deploy(ctx, req, "preview") +} + +// PutConfig implements client.Provider. +func (b *ByocAzure) PutConfig(context.Context, *defangv1.PutConfigRequest) error { + return errors.ErrUnsupported +} + +// QueryForDebug implements client.Provider. +func (b *ByocAzure) QueryForDebug(context.Context, *defangv1.DebugRequest) error { + return errors.ErrUnsupported +} + +// QueryLogs implements client.Provider. +func (b *ByocAzure) QueryLogs(context.Context, *defangv1.TailRequest) (client.ServerStream[defangv1.TailResponse], error) { + return nil, errors.ErrUnsupported +} + +// RemoteProjectName implements client.Provider. +// Subtle: this method shadows the method (*ByocBaseClient).RemoteProjectName of ByocAzure.ByocBaseClient. +func (b *ByocAzure) RemoteProjectName(context.Context) (string, error) { + return "", errors.ErrUnsupported +} + +// ServiceDNS implements client.Provider. +// Subtle: this method shadows the method (*ByocBaseClient).ServiceDNS of ByocAzure.ByocBaseClient. +func (b *ByocAzure) ServiceDNS(host string) string { + return host +} + +// Subscribe implements client.Provider. +func (b *ByocAzure) Subscribe(context.Context, *defangv1.SubscribeRequest) (client.ServerStream[defangv1.SubscribeResponse], error) { + return nil, errors.ErrUnsupported +} + +// TearDown implements client.Provider. +func (b *ByocAzure) TearDown(ctx context.Context) error { + return b.driver.TearDown(ctx) +} diff --git a/src/pkg/cli/client/byoc/do/stream.go b/src/pkg/cli/client/byoc/do/stream.go index 45d2b7c67..aa6f51555 100644 --- a/src/pkg/cli/client/byoc/do/stream.go +++ b/src/pkg/cli/client/byoc/do/stream.go @@ -42,7 +42,7 @@ func newByocServerStream(ctx context.Context, liveUrl string, etag types.ETag) ( liveURL.Scheme = "wss" } - conn, _, err := websocket.DefaultDialer.DialContext(ctx, liveURL.String(), nil) + conn, _, err := websocket.DefaultDialer.DialContext(ctx, liveURL.String(), nil) // TODO: should we close resp.Body? if err != nil { return nil, err } diff --git a/src/pkg/cli/client/byoc/gcp/byoc.go b/src/pkg/cli/client/byoc/gcp/byoc.go index bc4551077..737ee5292 100644 --- a/src/pkg/cli/client/byoc/gcp/byoc.go +++ b/src/pkg/cli/client/byoc/gcp/byoc.go @@ -29,7 +29,6 @@ import ( "github.com/DefangLabs/defang/src/pkg/term" "github.com/DefangLabs/defang/src/pkg/types" defangv1 "github.com/DefangLabs/defang/src/protos/io/defang/v1" - "github.com/aws/smithy-go/ptr" "github.com/bufbuild/connect-go" "google.golang.org/api/googleapi" auditpb "google.golang.org/genproto/googleapis/cloud/audit" @@ -225,12 +224,11 @@ func (b *ByocGcp) setUpCD(ctx context.Context) error { serviceAccount := path.Base(b.cdServiceAccount) if err := b.driver.SetupJob(ctx, "defang-cd", serviceAccount, []types.Container{ { - Image: b.CDImage, - Name: ecs.CdContainerName, - Cpus: 2.0, - Memory: 2048_000_000, // 2G - Essential: ptr.Bool(true), - WorkDir: "/app", + Image: b.CDImage, + Name: ecs.CdContainerName, + Cpus: 2.0, + Memory: 2048_000_000, // 2G + WorkDir: "/app", }, }); err != nil { return err @@ -319,6 +317,7 @@ type cdCommand struct { } func (b *ByocGcp) runCdCommand(ctx context.Context, cmd cdCommand) (string, error) { + // From https://www.pulumi.com/docs/iac/concepts/state-and-backends/#google-cloud-storage defangStateUrl := `gs://` + b.bucket pulumiBackendKey, pulumiBackendValue, err := byoc.GetPulumiBackend(defangStateUrl) if err != nil { diff --git a/src/pkg/cli/client/client.go b/src/pkg/cli/client/client.go index 4f8397d9e..cebc6a5b3 100644 --- a/src/pkg/cli/client/client.go +++ b/src/pkg/cli/client/client.go @@ -34,7 +34,6 @@ type FabricClient interface { PutDeployment(context.Context, *defangv1.PutDeploymentRequest) error RevokeToken(context.Context) error SetSelectedProvider(context.Context, *defangv1.SetSelectedProviderRequest) error - // Subscribe(context.Context, *v1.SubscribeRequest) (*v1.SubscribeResponse, error) Token(context.Context, *defangv1.TokenRequest) (*defangv1.TokenResponse, error) Track(string, ...Property) error VerifyDNSSetup(context.Context, *defangv1.VerifyDNSSetupRequest) error diff --git a/src/pkg/cli/client/playground.go b/src/pkg/cli/client/playground.go index 9dd02d1b8..c932705ee 100644 --- a/src/pkg/cli/client/playground.go +++ b/src/pkg/cli/client/playground.go @@ -128,4 +128,5 @@ func (g *PlaygroundProvider) QueryForDebug(ctx context.Context, req *defangv1.De func (g *PlaygroundProvider) PrepareDomainDelegation(ctx context.Context, req PrepareDomainDelegationRequest) (*PrepareDomainDelegationResponse, error) { return nil, nil // Playground does not support delegate domains } + func (g *PlaygroundProvider) SetCanIUseConfig(*defangv1.CanIUseResponse) {} diff --git a/src/pkg/cli/client/provider.go b/src/pkg/cli/client/provider.go index 93146cf10..192df7dc2 100644 --- a/src/pkg/cli/client/provider.go +++ b/src/pkg/cli/client/provider.go @@ -58,6 +58,7 @@ type Provider interface { SetCanIUseConfig(*defangv1.CanIUseResponse) Subscribe(context.Context, *defangv1.SubscribeRequest) (ServerStream[defangv1.SubscribeResponse], error) TearDown(context.Context) error + // Upload(context.Context, *defangv1.UploadURLRequest) (*defangv1.UploadURLResponse, error) } type Loader interface { diff --git a/src/pkg/cli/client/provider_id.go b/src/pkg/cli/client/provider_id.go index a69c6df9d..5fe9232b9 100644 --- a/src/pkg/cli/client/provider_id.go +++ b/src/pkg/cli/client/provider_id.go @@ -15,7 +15,7 @@ const ( ProviderAWS ProviderID = "aws" ProviderDO ProviderID = "digitalocean" ProviderGCP ProviderID = "gcp" - // ProviderAzure ProviderID = "azure" + ProviderAzure ProviderID = "azure" ) var allProviders = []ProviderID{ @@ -24,7 +24,7 @@ var allProviders = []ProviderID{ ProviderAWS, ProviderDO, ProviderGCP, - // ProviderAzure, + ProviderAzure, } func AllProviders() []ProviderID { @@ -89,6 +89,8 @@ func (p *ProviderID) SetValue(val defangv1.Provider) { *p = ProviderDO case defangv1.Provider_GCP: *p = ProviderGCP + case defangv1.Provider_AZURE: + *p = ProviderAzure default: *p = ProviderAuto } diff --git a/src/pkg/cli/client/region.go b/src/pkg/cli/client/region.go index 06844fd97..7d9a1559c 100644 --- a/src/pkg/cli/client/region.go +++ b/src/pkg/cli/client/region.go @@ -10,6 +10,8 @@ func GetRegion(provider ProviderID) string { return pkg.Getenv("CLOUDSDK_COMPUTE_REGION", "us-central1") // Default region for GCP case ProviderDO: return pkg.Getenv("DO_REGION", "nyc3") // Default region for DigitalOcean + case ProviderAzure: + return pkg.Getenv("AZURE_LOCATION", "westus") // Default region for Azure default: return "" // No default region for unsupported providers } diff --git a/src/pkg/cli/compose/context.go b/src/pkg/cli/compose/context.go index 18fb6bb42..b6a2a80fb 100644 --- a/src/pkg/cli/compose/context.go +++ b/src/pkg/cli/compose/context.go @@ -232,20 +232,22 @@ func uploadArchive(ctx context.Context, provider client.Provider, project string } // Do an HTTP PUT to the generated URL - resp, err := http.Put(ctx, res.Url, string(contentType), body) + header := http.Header{"Content-Type": []string{string(contentType)}} + header.Set("X-Ms-Blob-Type", "BlockBlob") // HACK: move to Azure provider + resp, err := http.PutWithHeader(ctx, res.Url, header, body) if err != nil { return "", err } defer resp.Body.Close() - if resp.StatusCode != 200 { + if resp.StatusCode != 200 && resp.StatusCode != 201 { return "", fmt.Errorf("HTTP PUT failed with status code %v", resp.Status) } - url := http.RemoveQueryParam(res.Url) - const gcpPrefix = "https://storage.googleapis.com/" - if strings.HasPrefix(url, gcpPrefix) { - url = "gs://" + url[len(gcpPrefix):] - } + url := res.Url //http.RemoveQueryParam(res.Url) // remove any access signature + + const gcpPrefix = "https://storage.googleapis.com/" // HACK: move to GCP provider + url = strings.Replace(url, gcpPrefix, "gs://", 1) + return url, nil } diff --git a/src/pkg/cli/connect.go b/src/pkg/cli/connect.go index 0d80f9424..fb8d19921 100644 --- a/src/pkg/cli/connect.go +++ b/src/pkg/cli/connect.go @@ -8,6 +8,7 @@ import ( "github.com/DefangLabs/defang/src/pkg" "github.com/DefangLabs/defang/src/pkg/cli/client" "github.com/DefangLabs/defang/src/pkg/cli/client/byoc/aws" + "github.com/DefangLabs/defang/src/pkg/cli/client/byoc/azure" "github.com/DefangLabs/defang/src/pkg/cli/client/byoc/do" "github.com/DefangLabs/defang/src/pkg/cli/client/byoc/gcp" "github.com/DefangLabs/defang/src/pkg/term" @@ -81,6 +82,8 @@ func NewProvider(ctx context.Context, providerID client.ProviderID, fabricClient provider = do.NewByocProvider(ctx, fabricClient.GetTenantName()) case client.ProviderGCP: provider = gcp.NewByocProvider(ctx, fabricClient.GetTenantName()) + case client.ProviderAzure: + provider = azure.NewByocProvider(ctx, fabricClient.GetTenantName()) default: provider = &client.PlaygroundProvider{FabricClient: fabricClient} } diff --git a/src/pkg/clouds/aws/common.go b/src/pkg/clouds/aws/common.go index 660e268f2..5bde7fb01 100644 --- a/src/pkg/clouds/aws/common.go +++ b/src/pkg/clouds/aws/common.go @@ -11,16 +11,10 @@ import ( "github.com/aws/aws-sdk-go-v2/credentials/processcreds" ) -type Region string - type Aws struct { Region Region } -func (r Region) String() string { - return string(r) -} - func (a *Aws) LoadConfig(ctx context.Context) (aws.Config, error) { cfg, err := LoadDefaultConfig(ctx, a.Region) if err != nil { diff --git a/src/pkg/clouds/aws/ecs/cfn/setup.go b/src/pkg/clouds/aws/ecs/cfn/setup.go index 0a220087b..9e27022b9 100644 --- a/src/pkg/clouds/aws/ecs/cfn/setup.go +++ b/src/pkg/clouds/aws/ecs/cfn/setup.go @@ -8,10 +8,10 @@ import ( "strings" "time" + "github.com/DefangLabs/defang/src/pkg/clouds/aws" common "github.com/DefangLabs/defang/src/pkg/clouds/aws" "github.com/DefangLabs/defang/src/pkg/clouds/aws/ecs" "github.com/DefangLabs/defang/src/pkg/clouds/aws/ecs/cfn/outputs" - "github.com/DefangLabs/defang/src/pkg/clouds/aws/region" "github.com/DefangLabs/defang/src/pkg/types" "github.com/aws/aws-sdk-go-v2/service/cloudformation" cfnTypes "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" @@ -37,7 +37,7 @@ func OptionVPCAndSubnetID(ctx context.Context, vpcID, subnetID string) func(type } } -func New(stack string, region region.Region) *AwsEcs { +func New(stack string, region aws.Region) *AwsEcs { if stack == "" { panic("stack must be set") } diff --git a/src/pkg/clouds/aws/ecs/cfn/setup_test.go b/src/pkg/clouds/aws/ecs/cfn/setup_test.go index 60022754a..05f399c16 100644 --- a/src/pkg/clouds/aws/ecs/cfn/setup_test.go +++ b/src/pkg/clouds/aws/ecs/cfn/setup_test.go @@ -9,7 +9,7 @@ import ( "time" "github.com/DefangLabs/defang/src/pkg" - "github.com/DefangLabs/defang/src/pkg/clouds/aws/region" + "github.com/DefangLabs/defang/src/pkg/clouds/aws" "github.com/DefangLabs/defang/src/pkg/types" ) @@ -21,7 +21,7 @@ func TestCloudFormation(t *testing.T) { retainBucket = false // delete bucket after test user := pkg.GetCurrentUser() // avoid conflict with other users in the same account - aws := New("crun-test-"+user, region.Region("us-west-2")) + aws := New("crun-test-"+user, aws.RegionUSWest2) if aws == nil { t.Fatal("aws is nil") } diff --git a/src/pkg/clouds/aws/ecs/cfn/template.go b/src/pkg/clouds/aws/ecs/cfn/template.go index 6a67c9950..fa9699382 100644 --- a/src/pkg/clouds/aws/ecs/cfn/template.go +++ b/src/pkg/clouds/aws/ecs/cfn/template.go @@ -377,20 +377,23 @@ func createTemplate(stack string, containers []types.Container, overrides Templa } var dependsOn []ecs.TaskDefinition_ContainerDependency - if container.DependsOn != nil { - for name, condition := range container.DependsOn { - dependsOn = append(dependsOn, ecs.TaskDefinition_ContainerDependency{ - Condition: ptr.String(string(condition)), - ContainerName: ptr.String(name), - }) + if !container.IsInit { + // Add COMPLETE dependencies to any init-containers + for _, c := range containers { + if c.IsInit { + dependsOn = append(dependsOn, ecs.TaskDefinition_ContainerDependency{ + Condition: ptr.String("COMPLETE"), + ContainerName: ptr.String(c.Name), + }) + } } } def := ecs.TaskDefinition_ContainerDefinition{ Name: name, Image: images[i], - StopTimeout: ptr.Int(120), // TODO: make this configurable - Essential: container.Essential, + StopTimeout: ptr.Int(120), // TODO: make this configurable + Essential: ptr.Bool(!container.IsInit), // init containers are not essential Cpu: cpuShares, LogConfiguration: &ecs.TaskDefinition_LogConfiguration{ LogDriver: "awslogs", diff --git a/src/pkg/clouds/aws/ecs/logs.go b/src/pkg/clouds/aws/ecs/logs.go index 12f6e731d..75d3223d7 100644 --- a/src/pkg/clouds/aws/ecs/logs.go +++ b/src/pkg/clouds/aws/ecs/logs.go @@ -9,7 +9,6 @@ import ( "time" "github.com/DefangLabs/defang/src/pkg/clouds/aws" - "github.com/DefangLabs/defang/src/pkg/clouds/aws/region" "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs" "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types" "github.com/aws/smithy-go/ptr" @@ -90,8 +89,8 @@ func TailLogGroup(ctx context.Context, input LogGroupInput) (LiveTailStream, err LogEventFilterPattern: pattern, } - region := region.FromArn(slti.LogGroupIdentifiers[0]) // must have at least one log group - cw, err := newCloudWatchLogsClient(ctx, region) // assume all log groups are in the same region + region := aws.RegionFromArn(slti.LogGroupIdentifiers[0]) // must have at least one log group + cw, err := newCloudWatchLogsClient(ctx, region) // assume all log groups are in the same region if err != nil { return nil, err } @@ -129,7 +128,7 @@ func QueryLogGroups(ctx context.Context, start, end time.Time, logGroups ...LogG } func QueryLogGroup(ctx context.Context, input LogGroupInput, start, end time.Time, cb func([]LogEvent) error) error { - region := region.FromArn(input.LogGroupARN) + region := aws.RegionFromArn(input.LogGroupARN) cw, err := newCloudWatchLogsClient(ctx, region) if err != nil { return err diff --git a/src/pkg/clouds/aws/ecs/status.go b/src/pkg/clouds/aws/ecs/status.go index c011a2713..87484a474 100644 --- a/src/pkg/clouds/aws/ecs/status.go +++ b/src/pkg/clouds/aws/ecs/status.go @@ -8,14 +8,13 @@ import ( "time" "github.com/DefangLabs/defang/src/pkg/clouds/aws" - "github.com/DefangLabs/defang/src/pkg/clouds/aws/region" "github.com/aws/aws-sdk-go-v2/service/ecs" ecsTypes "github.com/aws/aws-sdk-go-v2/service/ecs/types" ) // GetTaskStatus returns nil if the task is still running, io.EOF if the task is stopped successfully, or an error if the task failed. func GetTaskStatus(ctx context.Context, taskArn TaskArn) error { - region := region.FromArn(*taskArn) + region := aws.RegionFromArn(*taskArn) cluster, taskID := SplitClusterTask(taskArn) return getTaskStatus(ctx, region, cluster, taskID) } diff --git a/src/pkg/clouds/aws/ecs/tail.go b/src/pkg/clouds/aws/ecs/tail.go index 40b7f96de..128010d2e 100644 --- a/src/pkg/clouds/aws/ecs/tail.go +++ b/src/pkg/clouds/aws/ecs/tail.go @@ -8,7 +8,7 @@ import ( "time" "github.com/DefangLabs/defang/src/pkg" - "github.com/DefangLabs/defang/src/pkg/clouds/aws/region" + "github.com/DefangLabs/defang/src/pkg/clouds/aws" "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types" ) @@ -16,7 +16,7 @@ const AwsLogsStreamPrefix = CrunProjectName func (a *AwsEcs) Tail(ctx context.Context, taskArn TaskArn) error { taskId := GetTaskID(taskArn) - a.Region = region.FromArn(*taskArn) + a.Region = aws.RegionFromArn(*taskArn) es, err := a.TailTaskID(ctx, taskId) if err != nil { return err diff --git a/src/pkg/clouds/aws/region.go b/src/pkg/clouds/aws/region.go new file mode 100644 index 000000000..cf14a541a --- /dev/null +++ b/src/pkg/clouds/aws/region.go @@ -0,0 +1,53 @@ +package aws + +import ( + "strings" +) + +type Region string + +func (r Region) String() string { + return string(r) +} + +const ( + RegionAFSouth1 Region = "af-south-1" + RegionAPEast1 Region = "ap-east-1" + RegionAPNortheast1 Region = "ap-northeast-1" + RegionAPNortheast2 Region = "ap-northeast-2" + RegionAPNortheast3 Region = "ap-northeast-3" + RegionAPSouth1 Region = "ap-south-1" + RegionAPSouth2 Region = "ap-south-2" + RegionAPSoutheast1 Region = "ap-southeast-1" + RegionAPSoutheast2 Region = "ap-southeast-2" + RegionAPSoutheast3 Region = "ap-southeast-3" + RegionAPSoutheast4 Region = "ap-southeast-4" + RegionCACentral Region = "ca-central-1" + RegionCNNorth1 Region = "cn-north-1" + RegionCNNorthwest1 Region = "cn-northwest-1" + RegionEUCentral1 Region = "eu-central-1" + RegionEUCentral2 Region = "eu-central-2" + RegionEUNorth1 Region = "eu-north-1" + RegionEUSouth1 Region = "eu-south-1" + RegionEUSouth2 Region = "eu-south-2" + RegionEUWest1 Region = "eu-west-1" + RegionEUWest2 Region = "eu-west-2" + RegionEUWest3 Region = "eu-west-3" + RegionMECentral1 Region = "me-central-1" + RegionMESouth1 Region = "me-south-1" + RegionSAEast1 Region = "sa-east-1" + RegionUSGovEast1 Region = "us-gov-east-1" + RegionUSGovWest1 Region = "us-gov-west-1" + RegionUSEast1 Region = "us-east-1" + RegionUSEast2 Region = "us-east-2" + RegionUSWest1 Region = "us-west-1" + RegionUSWest2 Region = "us-west-2" +) + +func RegionFromArn(arn string) Region { + parts := strings.Split(arn, ":") + if len(parts) < 6 || parts[0] != "arn" { + panic("invalid ARN") + } + return Region(parts[3]) +} diff --git a/src/pkg/clouds/aws/region/region.go b/src/pkg/clouds/aws/region/region.go deleted file mode 100644 index 9b3359cb0..000000000 --- a/src/pkg/clouds/aws/region/region.go +++ /dev/null @@ -1,51 +0,0 @@ -package region - -import ( - "strings" - - "github.com/DefangLabs/defang/src/pkg/clouds/aws" -) - -type Region = aws.Region - -const ( - AFSouth1 Region = "af-south-1" - APEast1 Region = "ap-east-1" - APNortheast1 Region = "ap-northeast-1" - APNortheast2 Region = "ap-northeast-2" - APNortheast3 Region = "ap-northeast-3" - APSouth1 Region = "ap-south-1" - APSouth2 Region = "ap-south-2" - APSoutheast1 Region = "ap-southeast-1" - APSoutheast2 Region = "ap-southeast-2" - APSoutheast3 Region = "ap-southeast-3" - APSoutheast4 Region = "ap-southeast-4" - CACentral Region = "ca-central-1" - CNNorth1 Region = "cn-north-1" - CNNorthwest1 Region = "cn-northwest-1" - EUCentral1 Region = "eu-central-1" - EUCentral2 Region = "eu-central-2" - EUNorth1 Region = "eu-north-1" - EUSouth1 Region = "eu-south-1" - EUSouth2 Region = "eu-south-2" - EUWest1 Region = "eu-west-1" - EUWest2 Region = "eu-west-2" - EUWest3 Region = "eu-west-3" - MECentral1 Region = "me-central-1" - MESouth1 Region = "me-south-1" - SAEast1 Region = "sa-east-1" - USGovEast1 Region = "us-gov-east-1" - USGovWest1 Region = "us-gov-west-1" - USEast1 Region = "us-east-1" - USEast2 Region = "us-east-2" - USWest1 Region = "us-west-1" - USWest2 Region = "us-west-2" -) - -func FromArn(arn string) Region { - parts := strings.Split(arn, ":") - if len(parts) < 6 || parts[0] != "arn" { - panic("invalid ARN") - } - return Region(parts[3]) -} diff --git a/src/pkg/clouds/azure/aci/common.go b/src/pkg/clouds/azure/aci/common.go new file mode 100644 index 000000000..7b813ee8c --- /dev/null +++ b/src/pkg/clouds/azure/aci/common.go @@ -0,0 +1,71 @@ +package aci + +import ( + "fmt" + "os" + + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerinstance/armcontainerinstance/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources/v2" + "github.com/DefangLabs/defang/src/pkg/clouds/azure" +) + +type ContainerInstance struct { + azure.Azure + containerGroupProps *armcontainerinstance.ContainerGroupPropertiesProperties + resourceGroupName string + StorageAccount string + BlobContainerName string +} + +func NewContainerInstance(resourceGroupPrefix string, location azure.Location) *ContainerInstance { + if location == "" { + location = azure.Location(os.Getenv("AZURE_LOCATION")) + } + return &ContainerInstance{ + Azure: azure.Azure{ + Location: location, + SubscriptionID: os.Getenv("AZURE_SUBSCRIPTION_ID"), + }, + resourceGroupName: resourceGroupPrefix + location.String(), + StorageAccount: os.Getenv("DEFANG_CD_BUCKET"), + } +} + +func (c ContainerInstance) newContainerGroupClient() (*armcontainerinstance.ContainerGroupsClient, error) { + cred, err := c.NewCreds() + if err != nil { + return nil, err + } + + clientFactory, err := armcontainerinstance.NewClientFactory(c.SubscriptionID, cred, nil) + if err != nil { + return nil, fmt.Errorf("failed to create container group client: %w", err) + } + return clientFactory.NewContainerGroupsClient(), nil +} + +func (c ContainerInstance) newContainerClient() (*armcontainerinstance.ContainersClient, error) { + cred, err := c.NewCreds() + if err != nil { + return nil, err + } + + clientFactory, err := armcontainerinstance.NewClientFactory(c.SubscriptionID, cred, nil) + if err != nil { + return nil, fmt.Errorf("failed to create container client: %w", err) + } + return clientFactory.NewContainersClient(), nil +} + +func (c ContainerInstance) newResourceGroupClient() (*armresources.ResourceGroupsClient, error) { + cred, err := c.NewCreds() + if err != nil { + return nil, err + } + + resourcesClientFactory, err := armresources.NewClientFactory(c.SubscriptionID, cred, nil) + if err != nil { + return nil, fmt.Errorf("failed to create resource group client: %w", err) + } + return resourcesClientFactory.NewResourceGroupsClient(), nil +} diff --git a/src/pkg/clouds/azure/aci/common_test.go b/src/pkg/clouds/azure/aci/common_test.go new file mode 100644 index 000000000..8d1db7b3b --- /dev/null +++ b/src/pkg/clouds/azure/aci/common_test.go @@ -0,0 +1,24 @@ +package aci + +import ( + "testing" + + "github.com/DefangLabs/defang/src/pkg" + "github.com/google/uuid" +) + +var testResourceGroupName = "crun-test-" + pkg.GetCurrentUser() // avoid conflict with other users in the same account + +func TestNewClient(t *testing.T) { + t.Setenv("AZURE_SUBSCRIPTION_ID", uuid.NewString()) + + c := NewContainerInstance(testResourceGroupName, "") + + client, err := c.newContainerGroupClient() + if err != nil { + t.Fatalf("Failed to create client: %v", err) + } + if client == nil { + t.Fatal("Expected non-nil client") + } +} diff --git a/src/pkg/clouds/azure/aci/run.go b/src/pkg/clouds/azure/aci/run.go new file mode 100644 index 000000000..c38664c05 --- /dev/null +++ b/src/pkg/clouds/azure/aci/run.go @@ -0,0 +1,68 @@ +package aci + +import ( + "context" + "fmt" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerinstance/armcontainerinstance/v2" + "github.com/DefangLabs/defang/src/pkg" + "github.com/DefangLabs/defang/src/pkg/types" +) + +type ContainerGroupName = types.TaskID + +// safeAppend is like append but avoids mutating any aliases of the slice. +func safeAppend[T any](slice []T, elems ...T) []T { + return append(slice[:len(slice):len(slice)], elems...) +} + +func (c *ContainerInstance) Run(ctx context.Context, env map[string]string, args ...string) (ContainerGroupName, error) { + containerGroupClient, err := c.newContainerGroupClient() + if err != nil { + return nil, err + } + + commandArgs := to.SliceOfPtrs(args...) + var envVars []*armcontainerinstance.EnvironmentVariable + for key, value := range env { + envVars = append(envVars, &armcontainerinstance.EnvironmentVariable{ + Name: to.Ptr(key), + Value: to.Ptr(value), + }) + } + + clone := *c.containerGroupProps + for i, container := range clone.Containers { + newProps := *container.Properties + newProps.Command = safeAppend(newProps.Command, commandArgs...) // TODO: probably should only be done for the first container + newProps.EnvironmentVariables = safeAppend(newProps.EnvironmentVariables, envVars...) + clone.Containers[i] = &armcontainerinstance.Container{ + Name: container.Name, + Properties: &newProps, + } + } + + groupName := containerGroupPrefix + pkg.RandomID() + group := armcontainerinstance.ContainerGroup{ + Name: to.Ptr(groupName), + Location: c.Location.Ptr(), + Properties: &clone, + } + _, err = containerGroupClient.BeginCreateOrUpdate(ctx, c.resourceGroupName, groupName, group, nil) + if err != nil { + return nil, fmt.Errorf("failed to create container group: %w", err) + } + + _, err = containerGroupClient.BeginStart(ctx, c.resourceGroupName, groupName, nil) + if err != nil { + return nil, fmt.Errorf("failed to start container group: %w", err) + } + + // createResponse.Done() + // res, err := createResponse.PollUntilDone(ctx, nil) + // if err != nil { + // return nil, err + // } + return &groupName, nil +} diff --git a/src/pkg/clouds/azure/aci/run_test.go b/src/pkg/clouds/azure/aci/run_test.go new file mode 100644 index 000000000..adcf6985f --- /dev/null +++ b/src/pkg/clouds/azure/aci/run_test.go @@ -0,0 +1,43 @@ +//go:build integration + +package aci + +import ( + "context" + "testing" + + "github.com/DefangLabs/defang/src/pkg/types" +) + +func TestRun(t *testing.T) { + t.SkipNow() // too slow for CI + + ctx := context.Background() + + containerInstance := NewContainerInstance(testResourceGroupName, "westeurope") + + err := containerInstance.SetUp(ctx, []types.Container{ + { + Name: "test-container", + Image: "library/alpine:latest", + }, + }) + if err != nil { + t.Fatalf("SetUp failed: %v", err) + } + + t.Cleanup(func() { + // err := containerInstance.TearDown(ctx) + // if err != nil { + // t.Fatalf("Failed to tear down container instance: %v", err) + // } + }) + + taskID, err := containerInstance.Run(ctx, nil) + if err != nil { + t.Fatalf("Run failed: %v", err) + } + if taskID == nil { + t.Fatal("Expected non-nil task ID") + } +} diff --git a/src/pkg/clouds/azure/aci/setup.go b/src/pkg/clouds/azure/aci/setup.go new file mode 100644 index 000000000..07dcf92fc --- /dev/null +++ b/src/pkg/clouds/azure/aci/setup.go @@ -0,0 +1,193 @@ +package aci + +import ( + "context" + "fmt" + "math" + "os" + "strings" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerinstance/armcontainerinstance/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage" + "github.com/DefangLabs/defang/src/pkg" + "github.com/DefangLabs/defang/src/pkg/types" +) + +const containerGroupPrefix = "defang-cd-" +const storageAccountPrefix = "defangcd" +const blobContainerName = "uploads" + +func (c *ContainerInstance) SetUp(ctx context.Context, containers []types.Container) error { + resourceGroupClient, err := c.newResourceGroupClient() + if err != nil { + return err + } + _, err = resourceGroupClient.CreateOrUpdate(ctx, c.resourceGroupName, armresources.ResourceGroup{ + Location: c.Location.Ptr(), + }, nil) + if err != nil { + return fmt.Errorf("failed to create resource group: %w", err) + } + + c.containerGroupProps = &armcontainerinstance.ContainerGroupPropertiesProperties{ + OSType: to.Ptr(armcontainerinstance.OperatingSystemTypesLinux), // TODO: from Platform + // Priority: to.Ptr(armcontainerinstance.ContainerGroupPrioritySpot), + RestartPolicy: to.Ptr(armcontainerinstance.ContainerGroupRestartPolicyNever), + } + if username := os.Getenv("DOCKERHUB_USERNAME"); username != "" { + c.containerGroupProps.ImageRegistryCredentials = append(c.containerGroupProps.ImageRegistryCredentials, &armcontainerinstance.ImageRegistryCredential{ + Server: to.Ptr("index.docker.io"), + Username: to.Ptr(username), + Password: to.Ptr(pkg.Getenv("DOCKERHUB_TOKEN", os.Getenv("DOCKERHUB_PASSWORD"))), + }) + } + + for _, container := range containers { + if container.IsInit { + properties := &armcontainerinstance.InitContainerPropertiesDefinition{ + Command: to.SliceOfPtrs(container.Command...), + Image: to.Ptr(container.Image), + } + c.containerGroupProps.InitContainers = append(c.containerGroupProps.InitContainers, &armcontainerinstance.InitContainerDefinition{ + Name: to.Ptr(container.Name), + Properties: properties, + }) + } else { + cpus := math.Max(0.01, container.Cpus) // ensure minimum CPU is 0.01 + memoryInGB := math.Max(0.1, float64(container.Memory)/1024.0/1024.0/1024.0) // convert from B to GB, minimum 0.1 + properties := &armcontainerinstance.ContainerProperties{ + Command: to.SliceOfPtrs(container.Command...), + Image: to.Ptr(container.Image), + Resources: &armcontainerinstance.ResourceRequirements{ + Requests: &armcontainerinstance.ResourceRequests{ + CPU: to.Ptr(math.Round(100*cpus) / 100), // round to 2 decimal places + MemoryInGB: to.Ptr(math.Round(10*memoryInGB) * 0.1), // Round to 1 decimal place + }, + }, + } + c.containerGroupProps.Containers = append(c.containerGroupProps.Containers, &armcontainerinstance.Container{ + Name: to.Ptr(container.Name), + Properties: properties, + }) + } + } + + _, err = c.SetUpStorageAccount(ctx) + if err != nil { + return fmt.Errorf("failed to get storage account name: %w", err) + } + + return nil +} + +func (c *ContainerInstance) TearDown(ctx context.Context) error { + resourceGroupClient, err := c.newResourceGroupClient() + if err != nil { + return err + } + deleteResponse, err := resourceGroupClient.BeginDelete(ctx, c.resourceGroupName, nil) + if err != nil { + return fmt.Errorf("failed to delete resource group: %w", err) + } + _, err = deleteResponse.PollUntilDone(ctx, nil) + if err != nil { + return err + } + + // TODO: delete storage account? + return nil +} + +func (c *ContainerInstance) getStorageAccount(ctx context.Context, accountsClient *armstorage.AccountsClient) (string, error) { + if c.StorageAccount != "" { + return c.StorageAccount, nil + } + + if sa := os.Getenv("AZURE_STORAGE_ACCOUNT"); sa != "" { + return sa, nil + } + + for pager := accountsClient.NewListByResourceGroupPager(c.resourceGroupName, nil); pager.More(); { + page, err := pager.NextPage(ctx) + if err != nil { + return "", fmt.Errorf("failed to list storage accounts: %w", err) + } + for _, account := range page.Value { + if strings.HasPrefix(*account.Name, storageAccountPrefix) && *account.Location == c.Location.String() { + return *account.Name, nil + } + } + } + return "", nil +} + +func (c *ContainerInstance) SetUpStorageAccount(ctx context.Context) (string, error) { + accountsClient, err := c.NewStorageAccountsClient() + if err != nil { + return "", err + } + + storageAccount, err := c.getStorageAccount(ctx, accountsClient) + if err != nil { + return "", err + } + + if storageAccount == "" { + storageAccount = storageAccountPrefix + pkg.RandomID() // unique storage account name + createResponse, err := accountsClient.BeginCreate(ctx, c.resourceGroupName, storageAccount, armstorage.AccountCreateParameters{ + Kind: to.Ptr(armstorage.KindStorageV2), + Location: c.Location.Ptr(), + SKU: &armstorage.SKU{Name: to.Ptr(armstorage.SKUNameStandardLRS)}, + }, nil) + if err != nil { + return "", fmt.Errorf("failed to create storage account: %w", err) + } + + _, err = createResponse.PollUntilDone(ctx, nil) + if err != nil { + return "", fmt.Errorf("failed to poll storage account creation: %w", err) + } + } + c.StorageAccount = storageAccount + + // Assign permissions + // objectId, err := getCurrentUserObjectID(ctx) + // if err != nil { + // return "", fmt.Errorf("failed to get current user object ID: %w", err) + // } + // println("Current user object ID:", objectId) + + // if err := c.assignBlobDataContributor(ctx, objectId); err != nil { + // return "", fmt.Errorf("failed to assign blob data contributor role: %w", err) + // } + + // client, err := c.NewStorageAccountsClient() + // if err != nil { + // return "", fmt.Errorf("failed to create storage accounts client: %w", err) + // } + // lk, err := client.ListKeys(ctx, c.resourceGroupName, storageAccount, nil) + // if err != nil { + // return "", fmt.Errorf("failed to list storage account keys: %w", err) + // } + + // ss, err := client.RegenerateKey(ctx, c.resourceGroupName, storageAccount, armstorage.RegenerateKeyParameters{ + // KeyName: to.Ptr("key1"), + // }, nil) + // if err != nil { + // return "", fmt.Errorf("failed to regenerate storage account key: %w", err) + // } + + containerClient, err := c.NewBlobContainersClient() + if err != nil { + return "", fmt.Errorf("failed to create storage client: %w", err) + } + container, err := containerClient.Create(ctx, c.resourceGroupName, storageAccount, blobContainerName, armstorage.BlobContainer{}, nil) + if err != nil { + return "", fmt.Errorf("failed to create blob container: %w", err) + } + c.BlobContainerName = *container.Name + + return storageAccount, nil +} diff --git a/src/pkg/clouds/azure/aci/setup_test.go b/src/pkg/clouds/azure/aci/setup_test.go new file mode 100644 index 000000000..c7ae0ac7b --- /dev/null +++ b/src/pkg/clouds/azure/aci/setup_test.go @@ -0,0 +1,39 @@ +//go:build integration + +package aci + +import ( + "context" + "testing" + + "github.com/DefangLabs/defang/src/pkg/types" +) + +func TestSetup(t *testing.T) { + if testing.Short() { + t.Skip("skipping slow integration test in short mode") + } + + c := NewContainerInstance(testResourceGroupName, "westeurope") + + t.Run("SetUp", func(t *testing.T) { + err := c.SetUp(context.Background(), []types.Container{ + { + Name: "test-container", + Image: "library/nginx:latest", + Cpus: 1, + Memory: 1024 * 1024 * 1024, // 1 GB in B + }, + }) + if err != nil { + t.Errorf("Failed to set up container instance: %v", err) + } + }) + + t.Run("TearDown", func(t *testing.T) { + err := c.TearDown(context.Background()) + if err != nil { + t.Fatalf("Failed to tear down container instance: %v", err) + } + }) +} diff --git a/src/pkg/clouds/azure/aci/stop.go b/src/pkg/clouds/azure/aci/stop.go new file mode 100644 index 000000000..e7c168269 --- /dev/null +++ b/src/pkg/clouds/azure/aci/stop.go @@ -0,0 +1,18 @@ +package aci + +import ( + "context" +) + +func (c *ContainerInstance) Stop(ctx context.Context, groupName ContainerGroupName) error { + containerGroupClient, err := c.newContainerGroupClient() + if err != nil { + return err + } + + _, err = containerGroupClient.Stop(ctx, c.resourceGroupName, *groupName, nil) + if err != nil { + return err + } + return nil +} diff --git a/src/pkg/clouds/azure/aci/tail.go b/src/pkg/clouds/azure/aci/tail.go new file mode 100644 index 000000000..998087504 --- /dev/null +++ b/src/pkg/clouds/azure/aci/tail.go @@ -0,0 +1,127 @@ +package aci + +import ( + "context" + "errors" + "fmt" + "io" + "net/http" + "os" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerinstance/armcontainerinstance/v2" + "github.com/gorilla/websocket" +) + +type logEntry struct { + Message string + Stderr bool + Err error +} + +func (c *ContainerInstance) Tail(ctx context.Context, groupName ContainerGroupName) error { + container := c.containerGroupProps.Containers[0] + + ch, err := c.StreamLogs(ctx, groupName, *container.Name) + if err != nil { + return err + } + + for entry := range ch { + if entry.Err != nil { + return entry.Err + } + if entry.Stderr { + fmt.Fprint(os.Stderr, entry.Message) + } else { + fmt.Print(entry.Message) + } + } + return io.EOF +} + +func (c *ContainerInstance) QueryLogs(ctx context.Context, groupName ContainerGroupName, containerName string) (string, error) { + client, err := c.newContainerClient() + if err != nil { + return "", err + } + + for { + logResponse, err := client.ListLogs(ctx, c.resourceGroupName, *groupName, containerName, nil) + if err != nil { + var respErr *azcore.ResponseError + if errors.As(err, &respErr) && respErr.ErrorCode == "ContainerGroupDeploymentNotReady" { + time.Sleep(time.Second) // Wait before retrying + continue // Retry if the deployment is not ready yet + } + return "", fmt.Errorf("failed to list logs: %w", err) + } + if logResponse.Logs.Content == nil { + return "", io.EOF + } + return *logResponse.Logs.Content, nil + } +} + +func (c *ContainerInstance) StreamLogs(ctx context.Context, groupName ContainerGroupName, containerName string) (<-chan logEntry, error) { + client, err := c.newContainerClient() + if err != nil { + return nil, err + } + + var attachResponse armcontainerinstance.ContainersClientAttachResponse + for { + attachResponse, err = client.Attach(ctx, c.resourceGroupName, *groupName, containerName, nil) + if err != nil { + var respErr *azcore.ResponseError + if errors.As(err, &respErr) && respErr.ErrorCode == "ContainerNotFound" { + time.Sleep(time.Second) // Wait before retrying + continue // Retry if the container is not found yet + } + return nil, fmt.Errorf("failed to attach to container: %w", err) + } + break + } + + header := http.Header{} + header.Set("Authorization", *attachResponse.Password) + conn, resp, err := websocket.DefaultDialer.DialContext(ctx, *attachResponse.WebSocketURI, header) + defer resp.Body.Close() + if err != nil { + return nil, fmt.Errorf("failed to connect to websocket (%s): %w", resp.Status, err) + } + + ctx, cancel := context.WithCancel(ctx) + + go func() { + <-ctx.Done() + _ = conn.Close() // unblock conn.ReadMessage + }() + + ch := make(chan logEntry) + go func() { + defer close(ch) + defer cancel() + + for { + _, logLine, err := conn.ReadMessage() + if err != nil { + if !websocket.IsCloseError(err, websocket.CloseNormalClosure) { + select { + case ch <- logEntry{Err: err}: + case <-ctx.Done(): + } + } + return + } + stdioFd := logLine[0] + select { + case ch <- logEntry{Message: string(logLine[1:]), Stderr: stdioFd == 2}: + case <-ctx.Done(): + return + } + } + }() + return ch, nil +} diff --git a/src/pkg/clouds/azure/aci/tail_test.go b/src/pkg/clouds/azure/aci/tail_test.go new file mode 100644 index 000000000..0f6170c5c --- /dev/null +++ b/src/pkg/clouds/azure/aci/tail_test.go @@ -0,0 +1,57 @@ +//go:build integration + +package aci + +import ( + "context" + "io" + "testing" + + "github.com/DefangLabs/defang/src/pkg/types" +) + +func TestTail(t *testing.T) { + t.SkipNow() // too slow for CI + + ctx := context.Background() + + containerInstance := NewContainerInstance(testResourceGroupName, "westeurope") + + err := containerInstance.SetUp(ctx, []types.Container{ + { + Name: "test-container", + Image: "library/alpine:latest", + Command: []string{"sh", "-c", "sleep 3; cat /etc/hosts"}, + }, + }) + if err != nil { + t.Fatalf("SetUp failed: %v", err) + } + + t.Cleanup(func() { + // err := containerInstance.TearDown(ctx) + // if err != nil { + // t.Fatalf("Failed to tear down container instance: %v", err) + // } + }) + + taskID, err := containerInstance.Run(ctx, nil) + if err != nil { + t.Fatalf("Run failed: %v", err) + } + if taskID == nil { + t.Fatal("Expected non-nil task ID") + } + + t.Cleanup(func() { + err := containerInstance.Stop(ctx, taskID) + if err != nil { + t.Fatalf("Failed to stop container instance: %v", err) + } + }) + + err = containerInstance.Tail(ctx, taskID) + if err != io.EOF { + t.Fatalf("Tail failed: %v", err) + } +} diff --git a/src/pkg/clouds/azure/aci/upload.go b/src/pkg/clouds/azure/aci/upload.go new file mode 100644 index 000000000..f6749d635 --- /dev/null +++ b/src/pkg/clouds/azure/aci/upload.go @@ -0,0 +1,80 @@ +package aci + +import ( + "context" + "errors" + "fmt" + "net/url" + "os" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas" + "github.com/google/uuid" +) + +func (c *ContainerInstance) CreateUploadURL(ctx context.Context, blobName string) (string, error) { + if blobName == "" { + blobName = uuid.NewString() + } else { + if len(blobName) > 64 { + return "", errors.New("name must be less than 64 characters") + } + // Sanitize the digest so it's safe to use as a file name + blobName = strings.ReplaceAll(blobName, "/", "_") + // name = path.Join(buildsPath, tenantName.String(), digest); TODO: avoid collisions between tenants + } + if _, err := c.SetUpStorageAccount(ctx); err != nil { + return "", err + } + + now := time.Now().UTC() + expiry := now.Add(1 * time.Hour) + + // TODO: using user delegation is more secure than shared key, but requires the user to reauth to a OAuth2 client with the appropriate permissions to discover the user's ObjectID + // userCred, err := client.GetUserDelegationCredential(ctx, service.KeyInfo{ + // Start: to.Ptr(now.Format(time.RFC3339)), + // Expiry: to.Ptr(expiry.Format(time.RFC3339)), + // }, nil) + // if err != nil { + // return "", err + // } + + storageKey := os.Getenv("AZURE_STORAGE_KEY") + if storageKey == "" { + accountsClient, err := c.NewStorageAccountsClient() + if err != nil { + return "", err + } + + keys, err := accountsClient.ListKeys(ctx, c.resourceGroupName, c.StorageAccount, nil) + if err != nil { + return "", err + } + storageKey = *keys.Keys[0].Value // or [1]? + } + + keyCred, err := azblob.NewSharedKeyCredential(c.StorageAccount, storageKey) + if err != nil { + return "", err + } + + // Create SAS; TODO: how does AZURE_STORAGE_SAS_TOKEN env var work? + perms := sas.BlobPermissions{Create: true, Write: true, Read: true} // read is for ACR + sasQueryParams, err := sas.BlobSignatureValues{ + BlobName: blobName, + ContainerName: c.BlobContainerName, + ExpiryTime: expiry, + Permissions: perms.String(), + Protocol: sas.ProtocolHTTPS, + StartTime: now, + }.SignWithSharedKey(keyCred) + if err != nil { + return "", err + } + + serviceURL := fmt.Sprintf("https://%s.blob.core.windows.net/", c.StorageAccount) + sasURL := fmt.Sprintf("%s%s/%s?%s", serviceURL, c.BlobContainerName, url.PathEscape(blobName), sasQueryParams.Encode()) + return sasURL, nil +} diff --git a/src/pkg/clouds/azure/aci/upload_test.go b/src/pkg/clouds/azure/aci/upload_test.go new file mode 100644 index 000000000..40154810e --- /dev/null +++ b/src/pkg/clouds/azure/aci/upload_test.go @@ -0,0 +1,43 @@ +//go:build integration + +package aci + +import ( + "context" + "io" + "strings" + "testing" + + "github.com/DefangLabs/defang/src/pkg/http" +) + +func TestCreateUploadURL(t *testing.T) { + // Create a new container instance + container := NewContainerInstance("defang-cd", "westeurope") + + // Call the CreateUploadURL method + url, err := container.CreateUploadURL(context.Background(), "sha256-Jv4+base64/encoded_digest=") + if err != nil { + t.Fatalf("failed to create upload URL: %v", err) + } + + // Verify the URL is not empty + if url == "" { + t.Fatal("expected non-empty upload URL") + } + + t.Logf("Upload URL: %s", url) + header := http.Header{"Content-Type": []string{"application/text"}} + header.Set("X-Ms-Blob-Type", "BlockBlob") + resp, err := http.PutWithHeader(context.Background(), url, header, strings.NewReader("test content")) + if err != nil { + t.Fatalf("failed to upload content: %v", err) + } + defer resp.Body.Close() + + // Verify the response + if resp.StatusCode != 201 { + body, _ := io.ReadAll(resp.Body) + t.Fatalf("expected status OK, got %v: %s", resp.Status, body) + } +} diff --git a/src/pkg/clouds/azure/common.go b/src/pkg/clouds/azure/common.go new file mode 100644 index 000000000..5bdf0d7aa --- /dev/null +++ b/src/pkg/clouds/azure/common.go @@ -0,0 +1,69 @@ +package azure + +import ( + "errors" + "fmt" + + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage" +) + +type Azure struct { + Location Location + SubscriptionID string +} + +func (a Azure) NewCreds() (*azidentity.DefaultAzureCredential, error) { + if len(a.SubscriptionID) == 0 { + return nil, errors.New("environment variable AZURE_SUBSCRIPTION_ID is not set") + } + + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + return nil, fmt.Errorf("failed to create default Azure credentials: %w", err) + } + + return cred, nil +} + +func (a Azure) NewStorageAccountsClient() (*armstorage.AccountsClient, error) { + cred, err := a.NewCreds() + if err != nil { + return nil, err + } + + clientFactory, err := armstorage.NewClientFactory(a.SubscriptionID, cred, nil) + if err != nil { + return nil, fmt.Errorf("failed to create storage client: %w", err) + } + + return clientFactory.NewAccountsClient(), nil +} + +func (a Azure) NewBlobContainersClient() (*armstorage.BlobContainersClient, error) { + cred, err := a.NewCreds() + if err != nil { + return nil, err + } + + clientFactory, err := armstorage.NewClientFactory(a.SubscriptionID, cred, nil) + if err != nil { + return nil, fmt.Errorf("failed to create storage client: %w", err) + } + + return clientFactory.NewBlobContainersClient(), nil +} + +// func (a Azure) NewRoleAssignmentsClient() (*armauthorization.RoleAssignmentsClient, error) { +// cred, err := a.NewCreds() +// if err != nil { +// return nil, err +// } + +// clientFactory, err := armauthorization.NewRoleAssignmentsClient(a.SubscriptionID, cred, nil) +// if err != nil { +// return nil, fmt.Errorf("failed to create role assignments client: %w", err) +// } + +// return clientFactory, nil +// } diff --git a/src/pkg/clouds/azure/location.go b/src/pkg/clouds/azure/location.go new file mode 100644 index 000000000..d1023e243 --- /dev/null +++ b/src/pkg/clouds/azure/location.go @@ -0,0 +1,120 @@ +package azure + +type Location string + +const ( + LocationAsia Location = "asia" + LocationAsiaPacific Location = "asiapacific" + LocationAustralia Location = "australia" + LocationAustraliaCentral Location = "australiacentral" + LocationAustraliaCentral2 Location = "australiacentral2" + LocationAustraliaEast Location = "australiaeast" + LocationAustraliaSouthEast Location = "australiasoutheast" + LocationAustriaEast Location = "austriaeast" + LocationBrazil Location = "brazil" + LocationBrazilSouth Location = "brazilsouth" + LocationBrazilSouthEast Location = "brazilsoutheast" + LocationBrazilUS Location = "brazilus" + LocationCanada Location = "canada" + LocationCanadaCentral Location = "canadacentral" + LocationCanadaEast Location = "canadaeast" + LocationCentralIndia Location = "centralindia" + LocationCentralUS Location = "centralus" + LocationCentralUSEuap Location = "centraluseuap" + LocationCentralUSStage Location = "centralusstage" + LocationChileCentral Location = "chilecentral" + LocationEastAsia Location = "eastasia" + LocationEastAsiaStage Location = "eastasiastage" + LocationEastUS Location = "eastus" + LocationEastUS2 Location = "eastus2" + LocationEastUS2Euap Location = "eastus2euap" + LocationEastUS2Stage Location = "eastus2stage" + LocationEastUSStage Location = "eastusstage" + LocationEastUSStg Location = "eastusstg" + LocationEurope Location = "europe" + LocationFrance Location = "france" + LocationFranceCentral Location = "francecentral" + LocationFranceSouth Location = "francesouth" + LocationGermany Location = "germany" + LocationGermanyNorth Location = "germanynorth" + LocationGermanyWestCentral Location = "germanywestcentral" + LocationGlobal Location = "global" + LocationIndia Location = "india" + LocationIndonesia Location = "indonesia" + LocationIndonesiaCentral Location = "indonesiacentral" + LocationIsrael Location = "israel" + LocationIsraelCentral Location = "israelcentral" + LocationItaly Location = "italy" + LocationItalyNorth Location = "italynorth" + LocationJapan Location = "japan" + LocationJapanEast Location = "japaneast" + LocationJapanWest Location = "japanwest" + LocationJioIndiaCentral Location = "jioindiacentral" + LocationJioIndiaWest Location = "jioindiawest" + LocationKorea Location = "korea" + LocationKoreaCentral Location = "koreacentral" + LocationKoreaSouth Location = "koreasouth" + LocationMalaysia Location = "malaysia" + LocationMalaysiaWest Location = "malaysiawest" + LocationMexico Location = "mexico" + LocationMexicoCentral Location = "mexicocentral" + LocationNewZealand Location = "newzealand" + LocationNewZealandNorth Location = "newzealandnorth" + LocationNorthCentralUS Location = "northcentralus" + LocationNorthCentralUSStage Location = "northcentralusstage" + LocationNorthEurope Location = "northeurope" + LocationNorway Location = "norway" + LocationNorwayEast Location = "norwayeast" + LocationNorwayWest Location = "norwaywest" + LocationPoland Location = "poland" + LocationPolandCentral Location = "polandcentral" + LocationQatar Location = "qatar" + LocationQatarCentral Location = "qatarcentral" + LocationSingapore Location = "singapore" + LocationSouthAfrica Location = "southafrica" + LocationSouthAfricaNorth Location = "southafricanorth" + LocationSouthAfricaWest Location = "southafricawest" + LocationSouthCentralUS Location = "southcentralus" + LocationSouthCentralUSStage Location = "southcentralusstage" + LocationSouthCentralUSStg Location = "southcentralusstg" + LocationSoutheastAsia Location = "southeastasia" + LocationSoutheastAsiaStage Location = "southeastasiastage" + LocationSouthIndia Location = "southindia" + LocationSpain Location = "spain" + LocationSpainCentral Location = "spaincentral" + LocationSweden Location = "sweden" + LocationSwedenCentral Location = "swedencentral" + LocationSwedenSouth Location = "swedensouth" + LocationSwitzerland Location = "switzerland" + LocationSwitzerlandNorth Location = "switzerlandnorth" + LocationSwitzerlandWest Location = "switzerlandwest" + LocationTaiwan Location = "taiwan" + LocationUae Location = "uae" + LocationUaeCentral Location = "uaecentral" + LocationUaeNorth Location = "uaenorth" + LocationUK Location = "uk" + LocationUKSouth Location = "uksouth" + LocationUKWest Location = "ukwest" + LocationUnitedStates Location = "unitedstates" + LocationUnitedStatesEuap Location = "unitedstateseuap" + LocationWestCentralUS Location = "westcentralus" + LocationWestEurope Location = "westeurope" + LocationWestIndia Location = "westindia" + LocationWestUS Location = "westus" + LocationWestUS2 Location = "westus2" + LocationWestUS2Stage Location = "westus2stage" + LocationWestUS3 Location = "westus3" + LocationWestUSStage Location = "westusstage" +) + +func (l Location) String() string { + return string(l) +} + +func (l Location) Ptr() *string { + if l == "" { + return nil + } + s := string(l) + return &s +} diff --git a/src/pkg/clouds/gcp/cloudrun.go b/src/pkg/clouds/gcp/cloudrun.go index 1df57cd88..aad14329b 100644 --- a/src/pkg/clouds/gcp/cloudrun.go +++ b/src/pkg/clouds/gcp/cloudrun.go @@ -182,10 +182,10 @@ func (gcp Gcp) GetExecutionEnv(ctx context.Context, executionName string) (map[s } // FIXME: Add tests -func FixupGcpConfig(vCpu float32, memoryMiB uint64) (cpu float64, memory uint) { +func FixupGcpConfig(vCpu float64, memoryMiB uint64) (cpu float64, memory uint) { // Fixup CPU value and minimum memory according to // https://cloud.google.com/run/docs/configuring/jobs/cpu - cpu = math.Trunc(float64(vCpu)*100) / 100 // Cpu value below 1 should be in increments of 0.01 + cpu = math.Trunc(vCpu*100) / 100 // Cpu value below 1 should be in increments of 0.01 if cpu > 1 { cpu = math.Ceil(float64(vCpu)) // Any value above 1 must be an integer value } diff --git a/src/pkg/cmd/factory.go b/src/pkg/cmd/factory.go index 095cee2c0..ad8f4c603 100644 --- a/src/pkg/cmd/factory.go +++ b/src/pkg/cmd/factory.go @@ -4,51 +4,51 @@ import ( "fmt" "github.com/DefangLabs/defang/src/pkg" + "github.com/DefangLabs/defang/src/pkg/clouds/aws" "github.com/DefangLabs/defang/src/pkg/clouds/aws/ecs/cfn" - "github.com/DefangLabs/defang/src/pkg/clouds/aws/region" "github.com/DefangLabs/defang/src/pkg/docker" "github.com/DefangLabs/defang/src/pkg/types" ) type DriverOption func(types.Driver) error -func createDriver(reg Region, opts ...DriverOption) (types.Driver, error) { +func createDriver(reg aws.Region, opts ...DriverOption) (types.Driver, error) { var driver types.Driver switch reg { case "docker", "local", "": driver = docker.New() case - region.AFSouth1, // "af-south-1" - region.APEast1, // "ap-east-1" - region.APNortheast1, // "ap-northeast-1" - region.APNortheast2, // "ap-northeast-2" - region.APNortheast3, // "ap-northeast-3" - region.APSouth1, // "ap-south-1" - region.APSouth2, // "ap-south-2" - region.APSoutheast1, // "ap-southeast-1" - region.APSoutheast2, // "ap-southeast-2" - region.APSoutheast3, // "ap-southeast-3" - region.APSoutheast4, // "ap-southeast-4" - region.CACentral, // "ca-central-1" - region.CNNorth1, // "cn-north-1" - region.CNNorthwest1, // "cn-northwest-1" - region.EUCentral1, // "eu-central-1" - region.EUCentral2, // "eu-central-2" - region.EUNorth1, // "eu-north-1" - region.EUSouth1, // "eu-south-1" - region.EUSouth2, // "eu-south-2" - region.EUWest1, // "eu-west-1" - region.EUWest2, // "eu-west-2" - region.EUWest3, // "eu-west-3" - region.MECentral1, // "me-central-1" - region.MESouth1, // "me-south-1" - region.SAEast1, // "sa-east-1" - region.USGovEast1, // "us-gov-east-1" - region.USGovWest1, // "us-gov-west-1" - region.USEast1, // "us-east-1" - region.USEast2, // "us-east-2" - region.USWest1, // "us-west-1" - region.USWest2: // "us-west-2" + aws.RegionAFSouth1, // "af-south-1" + aws.RegionAPEast1, // "ap-east-1" + aws.RegionAPNortheast1, // "ap-northeast-1" + aws.RegionAPNortheast2, // "ap-northeast-2" + aws.RegionAPNortheast3, // "ap-northeast-3" + aws.RegionAPSouth1, // "ap-south-1" + aws.RegionAPSouth2, // "ap-south-2" + aws.RegionAPSoutheast1, // "ap-southeast-1" + aws.RegionAPSoutheast2, // "ap-southeast-2" + aws.RegionAPSoutheast3, // "ap-southeast-3" + aws.RegionAPSoutheast4, // "ap-southeast-4" + aws.RegionCACentral, // "ca-central-1" + aws.RegionCNNorth1, // "cn-north-1" + aws.RegionCNNorthwest1, // "cn-northwest-1" + aws.RegionEUCentral1, // "eu-central-1" + aws.RegionEUCentral2, // "eu-central-2" + aws.RegionEUNorth1, // "eu-north-1" + aws.RegionEUSouth1, // "eu-south-1" + aws.RegionEUSouth2, // "eu-south-2" + aws.RegionEUWest1, // "eu-west-1" + aws.RegionEUWest2, // "eu-west-2" + aws.RegionEUWest3, // "eu-west-3" + aws.RegionMECentral1, // "me-central-1" + aws.RegionMESouth1, // "me-south-1" + aws.RegionSAEast1, // "sa-east-1" + aws.RegionUSGovEast1, // "us-gov-east-1" + aws.RegionUSGovWest1, // "us-gov-west-1" + aws.RegionUSEast1, // "us-east-1" + aws.RegionUSEast2, // "us-east-2" + aws.RegionUSWest1, // "us-west-1" + aws.RegionUSWest2: // "us-west-2" driver = cfn.New(stackName(pkg.GetCurrentUser()), reg) default: return nil, fmt.Errorf("unsupported region: %v", reg) diff --git a/src/pkg/http/post.go b/src/pkg/http/post.go index 9740dfb37..67fae830d 100644 --- a/src/pkg/http/post.go +++ b/src/pkg/http/post.go @@ -36,11 +36,15 @@ func PostFormWithContext(ctx context.Context, url string, data url.Values) (*htt return PostWithContext(ctx, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) } -func PostWithContext(ctx context.Context, url, contentType string, body io.Reader) (*http.Response, error) { +func PostWithHeader(ctx context.Context, url string, header http.Header, body io.Reader) (*http.Response, error) { hreq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, body) if err != nil { return nil, err } - hreq.Header.Set("Content-Type", contentType) + hreq.Header = header return DefaultClient.Do(hreq) } + +func PostWithContext(ctx context.Context, url, contentType string, body io.Reader) (*http.Response, error) { + return PostWithHeader(ctx, url, http.Header{"Content-Type": []string{contentType}}, body) +} diff --git a/src/pkg/http/put.go b/src/pkg/http/put.go index 8304b72b4..7048863d5 100644 --- a/src/pkg/http/put.go +++ b/src/pkg/http/put.go @@ -18,10 +18,14 @@ import ( // See the Client.Do method documentation for details on how redirects // are handled. func Put(ctx context.Context, url string, contentType string, body io.Reader) (*http.Response, error) { + return PutWithHeader(ctx, url, http.Header{"Content-Type": []string{contentType}}, body) +} + +func PutWithHeader(ctx context.Context, url string, header http.Header, body io.Reader) (*http.Response, error) { req, err := http.NewRequestWithContext(ctx, http.MethodPut, url, body) if err != nil { return nil, err } - req.Header.Set("Content-Type", contentType) + req.Header = header return DefaultClient.Do(req) } diff --git a/src/pkg/types/driver.go b/src/pkg/types/driver.go index 20947d393..7e3ff1a67 100644 --- a/src/pkg/types/driver.go +++ b/src/pkg/types/driver.go @@ -9,28 +9,20 @@ const ( ) type TaskID *string -type ContainerCondition string - -const ( - ContainerStarted ContainerCondition = "START" - ContainerComplete = "COMPLETE" - ContainerSuccess = "SUCCESS" - ContainerHealthy = "HEALTHY" -) type Container struct { - Image string - Name string - Cpus float32 - Memory uint64 - Platform string - Essential *bool // default true + Image string + Name string + Cpus float64 + Memory uint64 + Platform string + IsInit bool // whether this container is an init container (non-essential) + Volumes []TaskVolume - VolumesFrom []string // container (default rw), container:rw, or container:ro + VolumesFrom []string // "container" (default rw), "container:rw", or "container:ro" EntryPoint []string Command []string // overridden by Run() - WorkDir string - DependsOn map[string]ContainerCondition // container name -> condition + WorkDir string // Deprecated: not supported by ACI } type TaskVolume struct { diff --git a/src/protos/io/defang/v1/fabric.pb.go b/src/protos/io/defang/v1/fabric.pb.go index a77f6ad74..3dd34648b 100644 --- a/src/protos/io/defang/v1/fabric.pb.go +++ b/src/protos/io/defang/v1/fabric.pb.go @@ -33,6 +33,7 @@ const ( Provider_AWS Provider = 2 Provider_DIGITALOCEAN Provider = 3 Provider_GCP Provider = 4 + Provider_AZURE Provider = 5 ) // Enum value maps for Provider. @@ -43,6 +44,7 @@ var ( 2: "AWS", 3: "DIGITALOCEAN", 4: "GCP", + 5: "AZURE", } Provider_value = map[string]int32{ "PROVIDER_UNSPECIFIED": 0, @@ -50,6 +52,7 @@ var ( "AWS": 2, "DIGITALOCEAN": 3, "GCP": 4, + "AZURE": 5, } ) @@ -3559,7 +3562,7 @@ type ProjectUpdate struct { Mode DeploymentMode `protobuf:"varint,6,opt,name=mode,proto3,enum=io.defang.v1.DeploymentMode" json:"mode,omitempty"` Provider Provider `protobuf:"varint,7,opt,name=provider,proto3,enum=io.defang.v1.Provider" json:"provider,omitempty"` ProjectOutputsVersion uint32 `protobuf:"varint,8,opt,name=project_outputs_version,json=projectOutputsVersion,proto3" json:"project_outputs_version,omitempty"` - ProjectOutputs []byte `protobuf:"bytes,9,opt,name=project_outputs,json=projectOutputs,proto3" json:"project_outputs,omitempty"` // JSON serialization of pulumi outputs. schema versioned using project_outputs_version + ProjectOutputs []byte `protobuf:"bytes,9,opt,name=project_outputs,json=projectOutputs,proto3" json:"project_outputs,omitempty"` // JSON serialization of pulumi outputs. schema unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -6274,295 +6277,296 @@ var file_io_defang_v1_fabric_proto_rawDesc = []byte{ 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x25, 0x0a, 0x0f, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x2a, 0x54, 0x0a, 0x08, 0x50, 0x72, 0x6f, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x2a, 0x5f, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x46, 0x41, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x57, 0x53, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x49, 0x47, 0x49, 0x54, 0x41, 0x4c, 0x4f, - 0x43, 0x45, 0x41, 0x4e, 0x10, 0x03, 0x12, 0x07, 0x0a, 0x03, 0x47, 0x43, 0x50, 0x10, 0x04, 0x2a, - 0x54, 0x0a, 0x0e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x44, 0x45, 0x56, 0x45, 0x4c, - 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x41, 0x47, - 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x44, 0x55, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x2a, 0xa3, 0x02, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x55, 0x49, - 0x4c, 0x44, 0x5f, 0x51, 0x55, 0x45, 0x55, 0x45, 0x44, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x42, - 0x55, 0x49, 0x4c, 0x44, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x49, 0x4e, - 0x47, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f, 0x50, 0x45, 0x4e, - 0x44, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f, - 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, - 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, - 0x12, 0x0a, 0x0e, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x49, 0x4e, - 0x47, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x51, 0x55, - 0x45, 0x55, 0x45, 0x44, 0x10, 0x07, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, - 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x08, 0x12, 0x18, - 0x0a, 0x14, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x4f, 0x4d, - 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x09, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x45, 0x50, 0x4c, - 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x0a, 0x12, - 0x10, 0x0a, 0x0c, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, - 0x0b, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, - 0x53, 0x43, 0x41, 0x4c, 0x45, 0x44, 0x5f, 0x49, 0x4e, 0x10, 0x0c, 0x2a, 0x42, 0x0a, 0x0a, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4f, 0x4e, - 0x46, 0x49, 0x47, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x53, 0x49, 0x54, 0x49, 0x56, 0x45, 0x10, 0x01, 0x2a, - 0x6a, 0x0a, 0x0e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x52, 0x59, 0x10, 0x01, 0x12, - 0x1a, 0x0a, 0x16, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x2a, 0x6b, 0x0a, 0x10, 0x44, - 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x21, 0x0a, 0x1d, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x43, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, - 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, - 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x02, 0x2a, 0x3f, 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, - 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x0f, 0x0a, 0x0b, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x5f, 0x41, 0x4d, - 0x44, 0x36, 0x34, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x5f, 0x41, - 0x52, 0x4d, 0x36, 0x34, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x5f, - 0x41, 0x4e, 0x59, 0x10, 0x02, 0x1a, 0x02, 0x18, 0x01, 0x2a, 0x48, 0x0a, 0x08, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x59, 0x10, 0x00, 0x12, 0x07, - 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x02, - 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x54, - 0x54, 0x50, 0x32, 0x10, 0x04, 0x12, 0x08, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x10, 0x05, 0x1a, - 0x02, 0x18, 0x01, 0x2a, 0x21, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x48, - 0x4f, 0x53, 0x54, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, - 0x10, 0x01, 0x1a, 0x02, 0x18, 0x01, 0x2a, 0x37, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, - 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x02, 0x1a, 0x02, 0x18, 0x01, 0x2a, - 0x61, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, - 0x69, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x49, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x4f, 0x42, 0x42, 0x59, 0x10, - 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x45, 0x52, 0x53, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x02, 0x12, - 0x07, 0x0a, 0x03, 0x50, 0x52, 0x4f, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x45, 0x41, 0x4d, - 0x10, 0x04, 0x32, 0x8b, 0x1a, 0x0a, 0x10, 0x46, 0x61, 0x62, 0x72, 0x69, 0x63, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x69, - 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x40, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, - 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x40, 0x0a, 0x05, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x12, 0x1a, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, - 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x52, - 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x04, 0x54, 0x61, - 0x69, 0x6c, 0x12, 0x19, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, + 0x43, 0x45, 0x41, 0x4e, 0x10, 0x03, 0x12, 0x07, 0x0a, 0x03, 0x47, 0x43, 0x50, 0x10, 0x04, 0x12, + 0x09, 0x0a, 0x05, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x10, 0x05, 0x2a, 0x54, 0x0a, 0x0e, 0x44, 0x65, + 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, + 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, + 0x54, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x41, 0x47, 0x49, 0x4e, 0x47, 0x10, 0x02, + 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x44, 0x55, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, + 0x2a, 0xa3, 0x02, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f, 0x51, 0x55, + 0x45, 0x55, 0x45, 0x44, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f, + 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x11, + 0x0a, 0x0d, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, + 0x03, 0x12, 0x14, 0x0a, 0x10, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, + 0x41, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, 0x42, 0x55, 0x49, 0x4c, 0x44, + 0x5f, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x12, 0x0a, 0x0e, 0x42, 0x55, + 0x49, 0x4c, 0x44, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x06, 0x12, 0x11, + 0x0a, 0x0d, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x51, 0x55, 0x45, 0x55, 0x45, 0x44, 0x10, + 0x07, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, + 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x45, 0x50, + 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, + 0x44, 0x10, 0x09, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, + 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x0a, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x55, + 0x49, 0x4c, 0x44, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x0b, 0x12, 0x18, 0x0a, 0x14, + 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x43, 0x41, 0x4c, 0x45, + 0x44, 0x5f, 0x49, 0x4e, 0x10, 0x0c, 0x2a, 0x42, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, + 0x45, 0x4e, 0x53, 0x49, 0x54, 0x49, 0x56, 0x45, 0x10, 0x01, 0x2a, 0x6a, 0x0a, 0x0e, 0x44, 0x65, + 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, + 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, + 0x17, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x52, 0x59, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x45, + 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x43, + 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x2a, 0x6b, 0x0a, 0x10, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x45, + 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, + 0x14, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x45, 0x50, 0x4c, 0x4f, + 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x4f, 0x57, + 0x4e, 0x10, 0x02, 0x2a, 0x3f, 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, + 0x0f, 0x0a, 0x0b, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x5f, 0x41, 0x4d, 0x44, 0x36, 0x34, 0x10, 0x00, + 0x12, 0x0f, 0x0a, 0x0b, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x5f, 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, + 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x5f, 0x41, 0x4e, 0x59, 0x10, 0x02, + 0x1a, 0x02, 0x18, 0x01, 0x2a, 0x48, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x59, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, + 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x48, + 0x54, 0x54, 0x50, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x54, 0x54, 0x50, 0x32, 0x10, 0x04, + 0x12, 0x08, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x10, 0x05, 0x1a, 0x02, 0x18, 0x01, 0x2a, 0x21, + 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x00, + 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x01, 0x1a, 0x02, 0x18, + 0x01, 0x2a, 0x37, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x0f, 0x0a, 0x0b, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, + 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, + 0x42, 0x4c, 0x49, 0x43, 0x10, 0x02, 0x1a, 0x02, 0x18, 0x01, 0x2a, 0x61, 0x0a, 0x10, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x65, 0x72, 0x12, 0x21, + 0x0a, 0x1d, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, + 0x49, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x4f, 0x42, 0x42, 0x59, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, + 0x50, 0x45, 0x52, 0x53, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x50, 0x52, + 0x4f, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x45, 0x41, 0x4d, 0x10, 0x04, 0x32, 0x8b, 0x1a, + 0x0a, 0x10, 0x46, 0x61, 0x62, 0x72, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, + 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x03, 0x90, + 0x02, 0x01, 0x12, 0x40, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, + 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, + 0x03, 0x90, 0x02, 0x01, 0x12, 0x40, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1a, 0x2e, + 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x64, + 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x04, 0x54, 0x61, 0x69, 0x6c, 0x12, 0x19, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x69, - 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3f, 0x0a, 0x06, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x15, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, - 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x1a, 0x19, 0x2e, 0x69, - 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x43, 0x0a, 0x06, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x12, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, - 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3f, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x18, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, - 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x03, 0x90, - 0x02, 0x01, 0x12, 0x48, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1b, 0x2e, 0x69, - 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x64, - 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x4b, 0x0a, 0x07, - 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x12, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, - 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, - 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x44, 0x0a, 0x07, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x73, 0x68, 0x12, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, - 0x4e, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x1e, 0x2e, 0x69, - 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x69, - 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, - 0x57, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x20, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, + 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3f, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x12, 0x15, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x1a, 0x19, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, + 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x43, 0x0a, 0x06, 0x44, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x12, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, + 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x70, 0x6c, 0x6f, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x03, + 0x47, 0x65, 0x74, 0x12, 0x18, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, + 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x48, 0x0a, + 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, + 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x4b, 0x0a, 0x07, 0x44, 0x65, 0x73, 0x74, 0x72, + 0x6f, 0x79, 0x12, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, + 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x03, 0x90, 0x02, 0x02, 0x12, 0x44, 0x0a, 0x07, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x12, + 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x4e, 0x0a, 0x09, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, + 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, + 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x57, 0x0a, 0x0b, 0x47, 0x65, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x69, 0x6f, 0x2e, 0x64, + 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x69, 0x6f, + 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, + 0x90, 0x02, 0x01, 0x12, 0x58, 0x0a, 0x0d, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, + 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, + 0x0d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x21, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x58, 0x0a, 0x0d, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x69, 0x6f, 0x2e, 0x64, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0e, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, - 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, - 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x40, 0x0a, - 0x05, 0x44, 0x65, 0x62, 0x75, 0x67, 0x12, 0x1a, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, - 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3a, 0x0a, 0x08, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x55, 0x4c, 0x41, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x08, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x54, 0x6f, 0x53, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x48, 0x0a, 0x09, - 0x50, 0x75, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x64, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x40, 0x0a, 0x05, 0x44, 0x65, 0x62, 0x75, + 0x67, 0x12, 0x1a, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, + 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, + 0x75, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x53, 0x69, + 0x67, 0x6e, 0x45, 0x55, 0x4c, 0x41, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x08, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, + 0x6f, 0x53, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x48, 0x0a, 0x09, 0x50, 0x75, 0x74, 0x53, 0x65, + 0x63, 0x72, 0x65, 0x74, 0x12, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x88, 0x02, + 0x01, 0x12, 0x43, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x73, 0x12, 0x15, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x4e, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, + 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x20, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, + 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, + 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x22, 0x06, + 0x88, 0x02, 0x01, 0x90, 0x02, 0x01, 0x12, 0x54, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x73, 0x12, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, + 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x48, 0x0a, 0x09, + 0x50, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x43, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x15, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, - 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x4e, 0x0a, 0x0b, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x20, 0x2e, 0x69, 0x6f, 0x2e, - 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x69, - 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x63, 0x72, - 0x65, 0x74, 0x73, 0x22, 0x06, 0x88, 0x02, 0x01, 0x90, 0x02, 0x01, 0x12, 0x54, 0x0a, 0x0a, 0x47, - 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x64, - 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x69, 0x6f, 0x2e, - 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x79, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x50, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x22, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, + 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x57, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x20, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, + 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x69, 0x6f, 0x2e, 0x64, + 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, - 0x01, 0x12, 0x48, 0x0a, 0x09, 0x50, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, - 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, - 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x50, 0x0a, 0x0d, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x22, 0x2e, 0x69, - 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x57, 0x0a, - 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x20, 0x2e, 0x69, + 0x01, 0x12, 0x50, 0x0a, 0x0d, 0x50, 0x75, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x12, 0x22, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x75, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, + 0x90, 0x02, 0x02, 0x12, 0x63, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x24, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, + 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, - 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x50, 0x0a, 0x0d, 0x50, 0x75, 0x74, 0x44, 0x65, 0x70, - 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x22, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, - 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x63, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x24, 0x2e, 0x69, 0x6f, - 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, - 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x25, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x52, 0x0a, - 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, - 0x12, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x70, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, - 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x2a, 0x2e, 0x69, 0x6f, 0x2e, - 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, - 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, - 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x28, 0x2e, 0x69, 0x6f, 0x2e, - 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, - 0x02, 0x12, 0x7b, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x2d, 0x2e, - 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x52, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, 0x12, 0x1e, 0x2e, 0x69, 0x6f, + 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x69, 0x6f, + 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x69, - 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x4a, - 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x2e, 0x69, - 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x43, 0x0a, 0x06, 0x57, 0x68, - 0x6f, 0x41, 0x6d, 0x49, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x69, - 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x68, 0x6f, 0x41, - 0x6d, 0x49, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, - 0x3b, 0x0a, 0x05, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x12, 0x1a, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, - 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x08, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x2a, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, + 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, + 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2b, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, + 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, + 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, + 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x28, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, + 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x64, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x7b, 0x0a, 0x18, + 0x47, 0x65, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x64, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x2d, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, + 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, + 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, + 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5a, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x4a, 0x0a, 0x0a, 0x53, 0x65, 0x74, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, + 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x52, 0x0a, - 0x0e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x44, 0x4e, 0x53, 0x53, 0x65, 0x74, 0x75, 0x70, 0x12, - 0x23, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x56, - 0x65, 0x72, 0x69, 0x66, 0x79, 0x44, 0x4e, 0x53, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, - 0x01, 0x12, 0x6f, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x28, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, - 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, - 0x02, 0x01, 0x12, 0x5c, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x28, 0x2e, 0x69, 0x6f, 0x2e, 0x64, - 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x02, - 0x12, 0x4b, 0x0a, 0x07, 0x43, 0x61, 0x6e, 0x49, 0x55, 0x73, 0x65, 0x12, 0x1c, 0x2e, 0x69, 0x6f, - 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x49, 0x55, - 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x64, - 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x49, 0x55, 0x73, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x49, 0x0a, - 0x08, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x64, - 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, - 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x12, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x42, 0xb0, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, - 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x46, 0x61, 0x62, 0x72, 0x69, 0x63, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x44, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x4c, 0x61, 0x62, 0x73, 0x2f, 0x64, 0x65, 0x66, 0x61, - 0x6e, 0x67, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x69, 0x6f, - 0x2f, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x65, 0x66, 0x61, 0x6e, - 0x67, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x49, 0x44, 0x58, 0xaa, 0x02, 0x0c, 0x49, 0x6f, 0x2e, 0x44, - 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, 0x49, 0x6f, 0x5c, 0x44, 0x65, - 0x66, 0x61, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x49, 0x6f, 0x5c, 0x44, 0x65, 0x66, - 0x61, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x0e, 0x49, 0x6f, 0x3a, 0x3a, 0x44, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x3a, - 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x43, 0x0a, 0x06, 0x57, 0x68, 0x6f, 0x41, 0x6d, 0x49, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, + 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x68, 0x6f, 0x41, 0x6d, 0x49, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x3b, 0x0a, 0x05, 0x54, 0x72, + 0x61, 0x63, 0x6b, 0x12, 0x1a, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x08, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x52, 0x0a, 0x0e, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x44, 0x4e, 0x53, 0x53, 0x65, 0x74, 0x75, 0x70, 0x12, 0x23, 0x2e, 0x69, 0x6f, 0x2e, + 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x44, 0x4e, 0x53, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x6f, 0x0a, 0x13, + 0x47, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x12, 0x28, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, + 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x5c, 0x0a, + 0x13, 0x53, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x12, 0x28, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0x4b, 0x0a, 0x07, 0x43, + 0x61, 0x6e, 0x49, 0x55, 0x73, 0x65, 0x12, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, + 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x49, 0x55, 0x73, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x49, 0x55, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x49, 0x0a, 0x08, 0x45, 0x73, 0x74, 0x69, + 0x6d, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, + 0x76, 0x31, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x12, 0x1c, + 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, + 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0xb0, 0x01, 0x0a, 0x10, + 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6f, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2e, 0x76, 0x31, + 0x42, 0x0b, 0x46, 0x61, 0x62, 0x72, 0x69, 0x63, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x44, 0x65, 0x66, 0x61, + 0x6e, 0x67, 0x4c, 0x61, 0x62, 0x73, 0x2f, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x2f, 0x73, 0x72, + 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x69, 0x6f, 0x2f, 0x64, 0x65, 0x66, 0x61, + 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x76, 0x31, 0xa2, 0x02, + 0x03, 0x49, 0x44, 0x58, 0xaa, 0x02, 0x0c, 0x49, 0x6f, 0x2e, 0x44, 0x65, 0x66, 0x61, 0x6e, 0x67, + 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, 0x49, 0x6f, 0x5c, 0x44, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x5c, + 0x56, 0x31, 0xe2, 0x02, 0x18, 0x49, 0x6f, 0x5c, 0x44, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x5c, 0x56, + 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, + 0x49, 0x6f, 0x3a, 0x3a, 0x44, 0x65, 0x66, 0x61, 0x6e, 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/src/protos/io/defang/v1/fabric.proto b/src/protos/io/defang/v1/fabric.proto index 178750ebb..229e97b2a 100644 --- a/src/protos/io/defang/v1/fabric.proto +++ b/src/protos/io/defang/v1/fabric.proto @@ -15,7 +15,7 @@ service FabricController { }; // public rpc GetVersion(google.protobuf.Empty) returns (Version) { option idempotency_level = NO_SIDE_EFFECTS; - }; // public + }; // public rpc Token(TokenRequest) returns (TokenResponse); // public rpc RevokeToken(google.protobuf.Empty) returns (google.protobuf.Empty); @@ -145,6 +145,7 @@ enum Provider { AWS = 2; DIGITALOCEAN = 3; GCP = 4; + AZURE = 5; } message GetSelectedProviderRequest { string project = 1; } @@ -255,8 +256,7 @@ message GenerateFilesRequest { string language = 2; bool agree_tos = 3; bool training_opt_out = 4; // only valid for Pro users - string model_id = 5; // only valid for Pro users - + string model_id = 5; // only valid for Pro users } message File { @@ -399,7 +399,7 @@ message PutDeploymentRequest { Deployment deployment = 1; } message ListDeploymentsRequest { string project = 1; DeploymentType type = 2; // active or all - uint32 limit = 3; // number of deployments to return + uint32 limit = 3; // number of deployments to return } message ListDeploymentsResponse { repeated Deployment deployments = 1; } @@ -479,18 +479,21 @@ message ProjectUpdate { DeploymentMode mode = 6; Provider provider = 7; uint32 project_outputs_version = 8; - bytes project_outputs = 9; // JSON serialization of pulumi outputs. schema versioned using project_outputs_version + bytes project_outputs = 9; // JSON serialization of pulumi outputs. schema + // versioned using project_outputs_version } enum Platform { - option deprecated = true; // still used by pulumi-defang provider in state files + option deprecated = + true; // still used by pulumi-defang provider in state files LINUX_AMD64 = 0; LINUX_ARM64 = 1; LINUX_ANY = 2; } message ServiceID { - option deprecated = true; // still used by pulumi-defang provider in state files + option deprecated = + true; // still used by pulumi-defang provider in state files string name = 1; string project = 2; } @@ -501,30 +504,34 @@ message GetRequest { // was ServiceID } message Device { - option deprecated = true; // still used by pulumi-defang provider in state files + option deprecated = + true; // still used by pulumi-defang provider in state files repeated string capabilities = 1; // "gpu", "tpu", etc. string driver = 2; // "nvidia", "amd", etc. uint32 count = 3; // number of devices to reserve } message Resource { - option deprecated = true; // still used by pulumi-defang provider in state files - float memory = 1; // in MiB - float cpus = 2; // fractional vCPUs + option deprecated = + true; // still used by pulumi-defang provider in state files + float memory = 1; // in MiB + float cpus = 2; // fractional vCPUs repeated Device devices = 3; // devices & capabilities } message Resources { - option deprecated = true; // still used by pulumi-defang provider in state files + option deprecated = + true; // still used by pulumi-defang provider in state files Resource reservations = 1; // requested resources // Resource limits = 2; // hard limits } message Deploy { - option deprecated = true; // still used by pulumi-defang provider in state files - uint32 replicas = 1; // number of initial replicas - Resources resources = 2; // reservations and limits + option deprecated = + true; // still used by pulumi-defang provider in state files + uint32 replicas = 1; // number of initial replicas + Resources resources = 2; // reservations and limits // Placement placement = 3; // EndpointMode endpoint_mode @@ -532,8 +539,9 @@ message Deploy { } enum Protocol { - option deprecated = true; // still used by pulumi-defang provider in state files - ANY = 0; // unspecified means any protocol + option deprecated = + true; // still used by pulumi-defang provider in state files + ANY = 0; // unspecified means any protocol UDP = 1; TCP = 2; HTTP = 3; @@ -542,13 +550,15 @@ enum Protocol { } enum Mode { - option deprecated = true; // still used by pulumi-defang provider in state files + option deprecated = + true; // still used by pulumi-defang provider in state files HOST = 0; // no load-balancer; suitable for internal services and functions INGRESS = 1; // with load-balancer; suitable for public services } message Port { - option deprecated = true; // still used by pulumi-defang provider in state files + option deprecated = + true; // still used by pulumi-defang provider in state files uint32 target = 1; Protocol protocol = 2; Mode mode = 3; // load-balanced (ingress) or not (host) @@ -558,22 +568,25 @@ message Port { } message Secret { - option deprecated = true; // still used by pulumi-defang provider in state files - string source = 1; // name of the secret + option deprecated = + true; // still used by pulumi-defang provider in state files + string source = 1; // name of the secret // string target = 2; } message Build { - option deprecated = true; // still used by pulumi-defang provider in state files - string context = 1; // path or URL to the build context - string dockerfile = 2; // path to the Dockerfile + option deprecated = + true; // still used by pulumi-defang provider in state files + string context = 1; // path or URL to the build context + string dockerfile = 2; // path to the Dockerfile map args = 3; // build-time variables float shm_size = 4; // in MiB string target = 5; } message HealthCheck { - option deprecated = true; // still used by pulumi-defang provider in state files + option deprecated = + true; // still used by pulumi-defang provider in state files repeated string test = 1; uint32 interval = 2; // in seconds uint32 timeout = 3; // in seconds; must be less than interval @@ -581,14 +594,16 @@ message HealthCheck { } enum Network { - option deprecated = true; // still used by pulumi-defang provider in state files - UNSPECIFIED = 0; // was: internal=false - PRIVATE = 1; // was: internal=true + option deprecated = + true; // still used by pulumi-defang provider in state files + UNSPECIFIED = 0; // was: internal=false + PRIVATE = 1; // was: internal=true PUBLIC = 2; } message Service { - option deprecated = true; // still used by pulumi-defang provider in state files + option deprecated = + true; // still used by pulumi-defang provider in state files string name = 1; string image = 2; Platform platform = 3; @@ -612,7 +627,8 @@ message Service { } message StaticFiles { - option deprecated = true; // still used by pulumi-defang provider in state files + option deprecated = + true; // still used by pulumi-defang provider in state files string folder = 1; repeated string redirects = 2; } @@ -669,13 +685,9 @@ message DelegateSubdomainZoneRequest { message DelegateSubdomainZoneResponse { string zone = 1; } -message DeleteSubdomainZoneRequest { - string project = 1; -} +message DeleteSubdomainZoneRequest { string project = 1; } -message GetDelegateSubdomainZoneRequest { - string project = 1; -} +message GetDelegateSubdomainZoneRequest { string project = 1; } enum SubscriptionTier { SUBSCRIPTION_TIER_UNSPECIFIED = 0; @@ -729,6 +741,4 @@ message PreviewRequest { string project_name = 6; } -message PreviewResponse { - string etag = 1; -} +message PreviewResponse { string etag = 1; }