diff --git a/docs/getting_started.md b/docs/getting_started.md index f2da82cf..4010b0b5 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -2,10 +2,10 @@ Tye is a tool that makes developing, testing, and deploying microservices and distributed applications easier. Project Tye includes a local orchestrator to make developing microservices easier and the ability to deploy microservices to Kubernetes with minimal configuration. -## Installing tye +## Installing Tye 1. Install [.NET Core 3.1](). -2. Install tye via the following command: +1. Install tye via the following command: ```text dotnet tool install -g Microsoft.Tye --version "0.7.0-alpha.21279.2" @@ -17,10 +17,19 @@ Tye is a tool that makes developing, testing, and deploying microservices and di dotnet tool update -g Microsoft.Tye --version "0.7.0-alpha.21279.2" ``` + > If using Mac and, if getting "command not found" errors when running `tye`, you may need to ensure that the `$HOME/.dotnet/tools` directory has been added to `PATH`. + > + > For example, add the following to the end of your `~/.zshrc` or `~/.zprofile`: + > + > ``` + > # Add .NET global tools (like Tye) to PATH. + > export PATH=$HOME/.dotnet/tools:$PATH + > ``` + ## Next steps 1. Once tye is installed, continue to the [Basic Tutorial](/docs/tutorials/hello-tye/00_run_locally.md). -2. Check out additional samples for more advanced concepts, such as using redis, rabbitmq, and service discovery. +1. Check out additional samples for more advanced concepts, such as using redis, rabbitmq, and service discovery. ## Working with CI builds diff --git a/docs/tutorials/hello-tye/00_run_locally.md b/docs/tutorials/hello-tye/00_run_locally.md index bfa72a37..3cab654c 100644 --- a/docs/tutorials/hello-tye/00_run_locally.md +++ b/docs/tutorials/hello-tye/00_run_locally.md @@ -1,6 +1,6 @@ # Frontend Backend sample with tye run -This tutorial will demonstrate how to use [`tye run`](/docs/reference/commandline/tye-run.md) to run a multi-project application. If you haven't so already, follow the [Getting Started Instructions](/docs/getting_started.md) to install tye. +This tutorial will demonstrate how to use [`tye run`](/docs/reference/commandline/tye-run.md) to run a multi-project application. If you haven't done so already, follow the [Getting Started Instructions](/docs/getting_started.md) to install tye. ## Running a single application with tye run @@ -28,7 +28,7 @@ This tutorial will demonstrate how to use [`tye run`](/docs/reference/commandlin The dashboard should show the `frontend` application running. - The `Logs` column has a link to view the streaming logs for the service. - - the `Bindings` column has links to the listening URLs of the service. + - The `Bindings` column has links to the listening URLs of the service. Navigate to the `frontend` service using one of the urls on the dashboard in the *Bindings* column. It should be in the form of or . diff --git a/docs/tutorials/hello-tye/01_deploy.md b/docs/tutorials/hello-tye/01_deploy.md index 2ac6440b..d71efe11 100644 --- a/docs/tutorials/hello-tye/01_deploy.md +++ b/docs/tutorials/hello-tye/01_deploy.md @@ -34,9 +34,9 @@ Now that we have our application running locally, let's deploy the application. You will be prompted to enter your container registry. This is needed to tag images, and to push them to a location accessible by kubernetes. - > :bulb: Under the hood `tye` uses `kubectl` and to execute deployments. In cases if you don't have `kubectl` installed or it's current context is invalid `tye deploy` will fail with the following error: "Drats! 'deploy' failed: Cannot apply manifests because kubectl is not installed." + > :bulb: Under the hood `tye` uses `kubectl` to execute deployments. In cases where you don't have `kubectl` installed or it's current context is invalid `tye deploy` will fail with the following error: "Drats! 'deploy' failed: Cannot apply manifests because kubectl is not installed." - If you are using dockerhub, the registry name will your dockerhub username. If you are a standalone container registry (for instance from your cloud provider), the registry name will look like a hostname, eg: `example.azurecr.io`. + If you are using dockerhub, the registry name will be your dockerhub username. If you use a standalone container registry (for instance from your cloud provider), the registry name will look like a hostname, eg: `example.azurecr.io`. `tye deploy` does many different things to deploy an application to Kubernetes. It will: - Create a docker image for each project in your application. @@ -77,9 +77,9 @@ Now that we have our application running locally, let's deploy the application. kubectl port-forward svc/frontend 5000:80 ``` - Now navigate to to view the frontend application working on Kubernetes. You should see the list of weather forecasts just like when you were running locally. + Now navigate to to view the frontend application running on Kubernetes. You should see the list of weather forecasts just like when you were running locally. - > :bulb: Currently `tye` does not provide a way to expose pods/services created to the public internet. We'll add features related to `Ingress` in future releases. + > :bulb: Currently `tye` does not provide a way to expose pods/services to the public internet. We'll add features related to `Ingress` in future releases. > :warning: Currently `tye` does not automatically enable TLS within the cluster, and so communication takes place over HTTP instead of HTTPS. This is typical way to deploy services in kubernetes - we may look to enable TLS as an option or by default in the future. @@ -128,11 +128,11 @@ Tye has a optional configuration file (`tye.yaml`) to allow customizing settings registry: ``` - If you are using dockerhub, the registry_name will your dockerhub username. If you are a standalone container registry (for instance from your cloud provider), the registry_name will look like a hostname, eg: `example.azurecr.io`. + If you are using dockerhub, the registry_name will your dockerhub username. If you use a standalone container registry (for instance from your cloud provider), the registry_name will look like a hostname, eg: `example.azurecr.io`. Now it's possible to use `tye deploy` without `--interactive` since the registry is stored as part of configuration. - > :question: This step may not make much sense if you're using `tye.yaml` to store a personal Dockerhub username. A more typical use case would storing the name of a private registry for use in a CI/CD system. + > :question: This step may not make much sense if you're using `tye.yaml` to store a personal Dockerhub username. A more typical use case would be storing the name of a private registry for use in a CI/CD system. ## Undeploying the application diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 275d7bbb..0bae44b0 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,25 +3,25 @@ - + https://github.com/dotnet/arcade - 78da7776965b428ff31da8f1ff2cb073506212b7 + 5619c32997ab2d6a5ddf6d2e488c572b882f891b - + https://github.com/dotnet/arcade - 78da7776965b428ff31da8f1ff2cb073506212b7 + 5619c32997ab2d6a5ddf6d2e488c572b882f891b - + https://github.com/dotnet/arcade - 78da7776965b428ff31da8f1ff2cb073506212b7 + 5619c32997ab2d6a5ddf6d2e488c572b882f891b - + https://github.com/dotnet/arcade - 78da7776965b428ff31da8f1ff2cb073506212b7 + 5619c32997ab2d6a5ddf6d2e488c572b882f891b - + https://github.com/dotnet/arcade - 78da7776965b428ff31da8f1ff2cb073506212b7 + 5619c32997ab2d6a5ddf6d2e488c572b882f891b https://github.com/dotnet/arcade-services diff --git a/eng/common/dotnet-install.sh b/eng/common/dotnet-install.sh index 06f56eeb..f3d1016c 100755 --- a/eng/common/dotnet-install.sh +++ b/eng/common/dotnet-install.sh @@ -70,7 +70,7 @@ case $cpuname in ;; esac -dotnetRoot="$repo_root/.dotnet" +dotnetRoot="${repo_root}.dotnet" if [[ $architecture != "" ]] && [[ $architecture != $buildarch ]]; then dotnetRoot="$dotnetRoot/$architecture" fi diff --git a/eng/common/internal-feed-operations.ps1 b/eng/common/internal-feed-operations.ps1 index 418c0993..92b77347 100644 --- a/eng/common/internal-feed-operations.ps1 +++ b/eng/common/internal-feed-operations.ps1 @@ -45,11 +45,11 @@ function SetupCredProvider { # Then, we set the 'VSS_NUGET_EXTERNAL_FEED_ENDPOINTS' environment variable to restore from the stable # feeds successfully - $nugetConfigPath = "$RepoRoot\NuGet.config" + $nugetConfigPath = Join-Path $RepoRoot "NuGet.config" if (-Not (Test-Path -Path $nugetConfigPath)) { Write-PipelineTelemetryError -Category 'Build' -Message 'NuGet.config file not found in repo root!' - ExitWithExitCode 1 + ExitWithExitCode 1 } $endpoints = New-Object System.Collections.ArrayList @@ -85,7 +85,7 @@ function SetupCredProvider { #Workaround for https://github.com/microsoft/msbuild/issues/4430 function InstallDotNetSdkAndRestoreArcade { - $dotnetTempDir = "$RepoRoot\dotnet" + $dotnetTempDir = Join-Path $RepoRoot "dotnet" $dotnetSdkVersion="2.1.507" # After experimentation we know this version works when restoring the SDK (compared to 3.0.*) $dotnet = "$dotnetTempDir\dotnet.exe" $restoreProjPath = "$PSScriptRoot\restore.proj" diff --git a/eng/common/internal-feed-operations.sh b/eng/common/internal-feed-operations.sh index e2233e78..9378223b 100755 --- a/eng/common/internal-feed-operations.sh +++ b/eng/common/internal-feed-operations.sh @@ -39,7 +39,7 @@ function SetupCredProvider { # Then, we set the 'VSS_NUGET_EXTERNAL_FEED_ENDPOINTS' environment variable to restore from the stable # feeds successfully - local nugetConfigPath="$repo_root/NuGet.config" + local nugetConfigPath="{$repo_root}NuGet.config" if [ ! "$nugetConfigPath" ]; then Write-PipelineTelemetryError -category 'Build' "NuGet.config file not found in repo's root!" diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index 65f1d75f..b1bca63a 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -34,7 +34,7 @@ function Print-Usage() { function Build([string]$target) { $logSuffix = if ($target -eq 'Execute') { '' } else { ".$target" } $log = Join-Path $LogDir "$task$logSuffix.binlog" - $outputPath = Join-Path $ToolsetDir "$task\\" + $outputPath = Join-Path $ToolsetDir "$task\" MSBuild $taskProject ` /bl:$log ` @@ -64,7 +64,7 @@ try { $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty } if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "16.8.0-preview3" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "16.10.0-preview2" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/sdl/execute-all-sdl-tools.ps1 b/eng/common/sdl/execute-all-sdl-tools.ps1 index 81b729f7..2881a560 100644 --- a/eng/common/sdl/execute-all-sdl-tools.ps1 +++ b/eng/common/sdl/execute-all-sdl-tools.ps1 @@ -32,7 +32,7 @@ try { $ErrorActionPreference = 'Stop' Set-StrictMode -Version 2.0 $disableConfigureToolsetImport = $true - $LASTEXITCODE = 0 + $global:LASTEXITCODE = 0 # `tools.ps1` checks $ci to perform some actions. Since the SDL # scripts don't necessarily execute in the same agent that run the diff --git a/eng/common/sdl/init-sdl.ps1 b/eng/common/sdl/init-sdl.ps1 index 1fe92711..3ac1d92b 100644 --- a/eng/common/sdl/init-sdl.ps1 +++ b/eng/common/sdl/init-sdl.ps1 @@ -10,7 +10,7 @@ Param( $ErrorActionPreference = 'Stop' Set-StrictMode -Version 2.0 $disableConfigureToolsetImport = $true -$LASTEXITCODE = 0 +$global:LASTEXITCODE = 0 # `tools.ps1` checks $ci to perform some actions. Since the SDL # scripts don't necessarily execute in the same agent that run the diff --git a/eng/common/sdl/run-sdl.ps1 b/eng/common/sdl/run-sdl.ps1 index fe95ab35..3d9c87ab 100644 --- a/eng/common/sdl/run-sdl.ps1 +++ b/eng/common/sdl/run-sdl.ps1 @@ -13,7 +13,7 @@ Param( $ErrorActionPreference = 'Stop' Set-StrictMode -Version 2.0 $disableConfigureToolsetImport = $true -$LASTEXITCODE = 0 +$global:LASTEXITCODE = 0 try { # `tools.ps1` checks $ci to perform some actions. Since the SDL diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml index 2acdd525..e8bc77d2 100644 --- a/eng/common/templates/job/onelocbuild.yml +++ b/eng/common/templates/job/onelocbuild.yml @@ -18,6 +18,9 @@ parameters: LclSource: lclFilesInRepo LclPackageId: '' RepoType: gitHub + GitHubOrg: dotnet + MirrorRepo: '' + MirrorBranch: main condition: '' jobs: @@ -66,6 +69,11 @@ jobs: ${{ if eq(parameters.RepoType, 'gitHub') }}: repoType: ${{ parameters.RepoType }} gitHubPatVariable: "${{ parameters.GithubPat }}" + ${{ if ne(parameters.MirrorRepo, '') }}: + isMirrorRepoSelected: true + gitHubOrganization: ${{ parameters.GitHubOrg }} + mirrorRepo: ${{ parameters.MirrorRepo }} + mirrorBranch: ${{ parameters.MirrorBranch }} condition: ${{ parameters.condition }} - task: PublishBuildArtifacts@1 diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml index a649d2b5..b58d4236 100644 --- a/eng/common/templates/job/source-index-stage1.yml +++ b/eng/common/templates/job/source-index-stage1.yml @@ -1,15 +1,19 @@ parameters: runAsPublic: false - sourceIndexPackageVersion: 1.0.1-20210421.1 + sourceIndexPackageVersion: 1.0.1-20210614.1 sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" preSteps: [] binlogPath: artifacts/log/Debug/Build.binlog pool: vmImage: vs2017-win2016 + condition: '' + dependsOn: '' jobs: - job: SourceIndexStage1 + dependsOn: ${{ parameters.dependsOn }} + condition: ${{ parameters.condition }} variables: - name: SourceIndexPackageVersion value: ${{ parameters.sourceIndexPackageVersion }} diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 89c55b18..6982bce8 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -193,38 +193,42 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { return $global:_DotNetInstallDir = $dotnetRoot } +function Retry($downloadBlock, $maxRetries = 5) { + $retries = 1 + + while($true) { + try { + & $downloadBlock + break + } + catch { + Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_ + } + + if (++$retries -le $maxRetries) { + $delayInSeconds = [math]::Pow(2, $retries) - 1 # Exponential backoff + Write-Host "Retrying. Waiting for $delayInSeconds seconds before next attempt ($retries of $maxRetries)." + Start-Sleep -Seconds $delayInSeconds + } + else { + Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Unable to download file in $maxRetries attempts." + break + } + + } +} + function GetDotNetInstallScript([string] $dotnetRoot) { $installScript = Join-Path $dotnetRoot 'dotnet-install.ps1' if (!(Test-Path $installScript)) { Create-Directory $dotnetRoot $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit - - $maxRetries = 5 - $retries = 1 - $uri = "https://dot.net/$dotnetInstallScriptVersion/dotnet-install.ps1" - while($true) { - try { - Write-Host "GET $uri" - Invoke-WebRequest $uri -OutFile $installScript - break - } - catch { - Write-Host "Failed to download '$uri'" - Write-Error $_.Exception.Message -ErrorAction Continue - } - - if (++$retries -le $maxRetries) { - $delayInSeconds = [math]::Pow(2, $retries) - 1 # Exponential backoff - Write-Host "Retrying. Waiting for $delayInSeconds seconds before next attempt ($retries of $maxRetries)." - Start-Sleep -Seconds $delayInSeconds - } - else { - throw "Unable to download file in $maxRetries attempts." - } - - } + Retry({ + Write-Host "GET $uri" + Invoke-WebRequest $uri -OutFile $installScript + }) } return $installScript @@ -308,8 +312,8 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = # If the version of msbuild is going to be xcopied, # use this version. Version matches a package here: - # https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=16.8.0-preview3&view=overview - $defaultXCopyMSBuildVersion = '16.8.0-preview3' + # https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=16.10.0-preview2&view=overview + $defaultXCopyMSBuildVersion = '16.10.0-preview2' if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools.vs } $vsMinVersionStr = if ($vsRequirements.version) { $vsRequirements.version } else { $vsMinVersionReqdStr } @@ -403,9 +407,13 @@ function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { } Create-Directory $packageDir + Write-Host "Downloading $packageName $packageVersion" $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit - Invoke-WebRequest "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/flat2/$packageName/$packageVersion/$packageName.$packageVersion.nupkg" -OutFile $packagePath + Retry({ + Invoke-WebRequest "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/flat2/$packageName/$packageVersion/$packageName.$packageVersion.nupkg" -OutFile $packagePath + }) + Unzip $packagePath $packageDir } @@ -442,27 +450,9 @@ function LocateVisualStudio([object]$vsRequirements = $null){ if (!(Test-Path $vsWhereExe)) { Create-Directory $vsWhereDir Write-Host 'Downloading vswhere' - $maxRetries = 5 - $retries = 1 - - while($true) { - try { - Invoke-WebRequest "https://netcorenativeassets.blob.core.windows.net/resource-packages/external/windows/vswhere/$vswhereVersion/vswhere.exe" -OutFile $vswhereExe - break - } - catch{ - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_ - } - - if (++$retries -le $maxRetries) { - $delayInSeconds = [math]::Pow(2, $retries) - 1 # Exponential backoff - Write-Host "Retrying. Waiting for $delayInSeconds seconds before next attempt ($retries of $maxRetries)." - Start-Sleep -Seconds $delayInSeconds - } - else { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Unable to download file in $maxRetries attempts." - } - } + Retry({ + Invoke-WebRequest "https://netcorenativeassets.blob.core.windows.net/resource-packages/external/windows/vswhere/$vswhereVersion/vswhere.exe" -OutFile $vswhereExe + }) } if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools.vs } @@ -498,7 +488,7 @@ function InitializeBuildTool() { if (Test-Path variable:global:_BuildTool) { # If the requested msbuild parameters do not match, clear the cached variables. if($global:_BuildTool.Contains('ExcludePrereleaseVS') -and $global:_BuildTool.ExcludePrereleaseVS -ne $excludePrereleaseVS) { - Remove-Item variable:global:_BuildTool + Remove-Item variable:global:_BuildTool Remove-Item variable:global:_MSBuildExe } else { return $global:_BuildTool @@ -555,7 +545,7 @@ function GetDefaultMSBuildEngine() { function GetNuGetPackageCachePath() { if ($env:NUGET_PACKAGES -eq $null) { - # Use local cache on CI to ensure deterministic build. + # Use local cache on CI to ensure deterministic build. # Avoid using the http cache as workaround for https://github.com/NuGet/Home/issues/3116 # use global cache in dev builds to avoid cost of downloading packages. # For directory normalization, see also: https://github.com/NuGet/Home/issues/7968 @@ -712,7 +702,10 @@ function MSBuild-Core() { } foreach ($arg in $args) { - if ($arg -ne $null -and $arg.Trim() -ne "") { + if ($null -ne $arg -and $arg.Trim() -ne "") { + if ($arg.EndsWith('\')) { + $arg = $arg + "\" + } $cmdArgs += " `"$arg`"" } } @@ -784,7 +777,7 @@ function Get-Darc($version) { . $PSScriptRoot\pipeline-logging-functions.ps1 -$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot '..\..') +$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot '..\..\') $EngRoot = Resolve-Path (Join-Path $PSScriptRoot '..') $ArtifactsDir = Join-Path $RepoRoot 'artifacts' $ToolsetDir = Join-Path $ArtifactsDir 'toolset' diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 0af84953..e0261236 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -485,13 +485,14 @@ _script_dir=`dirname "$_ResolvePath"` eng_root=`cd -P "$_script_dir/.." && pwd` repo_root=`cd -P "$_script_dir/../.." && pwd` -artifacts_dir="$repo_root/artifacts" +repo_root="${repo_root}/" +artifacts_dir="${repo_root}artifacts" toolset_dir="$artifacts_dir/toolset" -tools_dir="$repo_root/.tools" +tools_dir="${repo_root}.tools" log_dir="$artifacts_dir/log/$configuration" temp_dir="$artifacts_dir/tmp/$configuration" -global_json_file="$repo_root/global.json" +global_json_file="${repo_root}global.json" # determine if global.json contains a "runtimes" entry global_json_has_runtimes=false if command -v jq &> /dev/null; then @@ -504,7 +505,7 @@ fi # HOME may not be defined in some scenarios, but it is required by NuGet if [[ -z $HOME ]]; then - export HOME="$repo_root/artifacts/.home/" + export HOME="${repo_root}artifacts/.home/" mkdir -p "$HOME" fi diff --git a/global.json b/global.json index 6be781e0..c93475f2 100644 --- a/global.json +++ b/global.json @@ -11,6 +11,6 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21303.2" + "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21317.1" } } diff --git a/samples/apps-with-core-angular/MoviesApp/package-lock.json b/samples/apps-with-core-angular/MoviesApp/package-lock.json index 8790b513..672ddd47 100644 --- a/samples/apps-with-core-angular/MoviesApp/package-lock.json +++ b/samples/apps-with-core-angular/MoviesApp/package-lock.json @@ -2421,15 +2421,36 @@ } }, "browserslist": { - "version": "4.12.0", - "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/browserslist/-/browserslist-4.12.0.tgz", - "integrity": "sha1-BsbVcVoe3mxR/Dn/Z/1kf3QLZW0=", + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001043", - "electron-to-chromium": "^1.3.413", - "node-releases": "^1.1.53", - "pkg-up": "^2.0.0" + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + }, + "dependencies": { + "caniuse-lite": { + "version": "1.0.30001230", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz", + "integrity": "sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.739", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz", + "integrity": "sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A==", + "dev": true + }, + "node-releases": { + "version": "1.1.72", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz", + "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==", + "dev": true + } } }, "browserstack": { @@ -2899,6 +2920,12 @@ "simple-swizzle": "^0.2.2" } }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, "colors": { "version": "1.1.2", "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/colors/-/colors-1.1.2.tgz", @@ -4022,12 +4049,6 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, - "electron-to-chromium": { - "version": "1.3.434", - "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/electron-to-chromium/-/electron-to-chromium-1.3.434.tgz", - "integrity": "sha1-pn3LJo6Tdo4haTmZmcz/pHg/BI4=", - "dev": true - }, "elliptic": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", @@ -4293,6 +4314,12 @@ "es6-promise": "^4.0.3" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/escape-html/-/escape-html-1.0.3.tgz", @@ -4833,15 +4860,6 @@ } } }, - "find-up": { - "version": "2.1.0", - "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, "flatted": { "version": "2.0.2", "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/flatted/-/flatted-2.0.2.tgz", @@ -6534,16 +6552,6 @@ "json5": "^1.0.1" } }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -7286,12 +7294,6 @@ } } }, - "node-releases": { - "version": "1.1.55", - "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/node-releases/-/node-releases-1.1.55.tgz", - "integrity": "sha1-ivI7fFYdji5uNqRmN7q4RjOwfO4=", - "dev": true - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -7764,24 +7766,6 @@ "integrity": "sha1-kYzrrqJIpiz3/6uOO8qMX4gvxC4=", "dev": true }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, "p-map": { "version": "3.0.0", "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/p-map/-/p-map-3.0.0.tgz", @@ -7800,12 +7784,6 @@ "retry": "^0.12.0" } }, - "p-try": { - "version": "1.0.0", - "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, "pacote": { "version": "9.5.8", "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/pacote/-/pacote-9.5.8.tgz", @@ -8150,15 +8128,6 @@ } } }, - "pkg-up": { - "version": "2.0.0", - "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/pkg-up/-/pkg-up-2.0.0.tgz", - "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - }, "portfinder": { "version": "1.0.26", "resolved": "https://kdi.jfrog.io/kdi/api/npm/npm/portfinder/-/portfinder-1.0.26.tgz", diff --git a/samples/dapr/pub-sub/tye.yaml b/samples/dapr/pub-sub/tye.yaml index 1d151674..77d0683d 100644 --- a/samples/dapr/pub-sub/tye.yaml +++ b/samples/dapr/pub-sub/tye.yaml @@ -21,7 +21,7 @@ extensions: # # config: myconfig - # components-path configures the components path of the dapr sidecard + # components-path configures the components path of the dapr sidecar components-path: "./components/" # You can instruct Tye to not create the Dapr placement container on your behalf. This is required if you have Dapr running and want to use that container. diff --git a/src/Microsoft.Tye.Hosting/DockerRunner.cs b/src/Microsoft.Tye.Hosting/DockerRunner.cs index ba193b69..4a235285 100644 --- a/src/Microsoft.Tye.Hosting/DockerRunner.cs +++ b/src/Microsoft.Tye.Hosting/DockerRunner.cs @@ -79,6 +79,11 @@ namespace Microsoft.Tye.Hosting continue; } + if (string.Equals(binding.Protocol, "udp", StringComparison.InvariantCultureIgnoreCase)) + { + throw new CommandException("Proxy does not support the udp protocol yet."); + } + var b = new ServiceBinding() { ConnectionString = binding.ConnectionString, @@ -232,7 +237,7 @@ namespace Microsoft.Tye.Hosting // These are the ports that the application should use for binding // 1. Tell the docker container what port to bind to - portString = docker.Private ? "" : string.Join(" ", ports.Select(p => $"-p {p.Port}:{p.ContainerPort ?? p.Port}")); + portString = docker.Private ? "" : string.Join(" ", ports.Select(p => $"-p {p.Port}:{p.ContainerPort ?? p.Port}{(string.Equals(p.Protocol, "udp", StringComparison.OrdinalIgnoreCase) ? "/udp" : string.Empty)}")); if (docker.IsAspNet) { diff --git a/src/Microsoft.Tye.Hosting/Model/Application.cs b/src/Microsoft.Tye.Hosting/Model/Application.cs index c91ade50..d88236cf 100644 --- a/src/Microsoft.Tye.Hosting/Model/Application.cs +++ b/src/Microsoft.Tye.Hosting/Model/Application.cs @@ -12,14 +12,19 @@ namespace Microsoft.Tye.Hosting.Model { public class Application { - public Application(FileInfo source, Dictionary services, ContainerEngine containerEngine) + public Application(string name, FileInfo source, Dictionary services, ContainerEngine containerEngine) { + Name = name; Source = source.FullName; ContextDirectory = source.DirectoryName!; Services = services; ContainerEngine = containerEngine; } + public string Id { get; } = Guid.NewGuid().ToString(); + + public string Name { get; } + public string Source { get; } public string ContextDirectory { get; } diff --git a/src/Microsoft.Tye.Hosting/Model/V1/V1Application.cs b/src/Microsoft.Tye.Hosting/Model/V1/V1Application.cs new file mode 100644 index 00000000..b646dbb3 --- /dev/null +++ b/src/Microsoft.Tye.Hosting/Model/V1/V1Application.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Tye.Hosting.Model.V1 +{ + public class V1Application + { + public string? Id { get; set; } + + public string? Name { get; set; } + + public string? Source { get; set; } + } +} diff --git a/src/Microsoft.Tye.Hosting/ProxyService.cs b/src/Microsoft.Tye.Hosting/ProxyService.cs index 24d6f61a..7e85860d 100644 --- a/src/Microsoft.Tye.Hosting/ProxyService.cs +++ b/src/Microsoft.Tye.Hosting/ProxyService.cs @@ -63,6 +63,11 @@ namespace Microsoft.Tye.Hosting continue; } + if (string.Equals(binding.Protocol, "udp", StringComparison.InvariantCultureIgnoreCase)) + { + throw new CommandException("Proxy does not support the udp protocol yet."); + } + var ports = binding.ReplicaPorts; // We need to bind to all interfaces on linux since the container -> host communication won't work diff --git a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs index 64a06f28..8c454a36 100644 --- a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs +++ b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs @@ -37,6 +37,7 @@ namespace Microsoft.Tye.Hosting public void MapRoutes(IEndpointRouteBuilder endpoints) { endpoints.MapGet("/api/v1", ServiceIndex); + endpoints.MapGet("/api/v1/application", ApplicationIndex); endpoints.MapDelete("/api/v1/control", ControlPlaneShutdown); endpoints.MapGet("/api/v1/services", Services); endpoints.MapGet("/api/v1/services/{name}", Service); @@ -50,15 +51,33 @@ namespace Microsoft.Tye.Hosting context.Response.ContentType = "application/json"; return JsonSerializer.SerializeAsync(context.Response.Body, new[] { + $"{context.Request.Scheme}://{context.Request.Host}/api/v1/application", $"{context.Request.Scheme}://{context.Request.Host}/api/v1/control", - $"{context.Request.Scheme}://{context.Request.Host}/api/v1/services", $"{context.Request.Scheme}://{context.Request.Host}/api/v1/logs/{{service}}", $"{context.Request.Scheme}://{context.Request.Host}/api/v1/metrics", $"{context.Request.Scheme}://{context.Request.Host}/api/v1/metrics/{{service}}", + $"{context.Request.Scheme}://{context.Request.Host}/api/v1/services", }, _options); } + private Task ApplicationIndex(HttpContext context) + { + var app = context.RequestServices.GetRequiredService(); + + context.Response.ContentType = "application/json"; + + return JsonSerializer.SerializeAsync( + context.Response.Body, + new V1Application + { + Id = app.Id, + Name = app.Name, + Source = app.Source + }, + _options); + } + private Task ControlPlaneShutdown(HttpContext context) { var lifetime = context.RequestServices.GetRequiredService(); diff --git a/src/tye/ApplicationBuilderExtensions.cs b/src/tye/ApplicationBuilderExtensions.cs index 3015564e..a3bab007 100644 --- a/src/tye/ApplicationBuilderExtensions.cs +++ b/src/tye/ApplicationBuilderExtensions.cs @@ -213,7 +213,7 @@ namespace Microsoft.Tye services.Add(ingress.Name, new Service(description)); } - return new Application(application.Source, services, application.ContainerEngine) { Network = application.Network }; + return new Application(application.Name, application.Source, services, application.ContainerEngine) { Network = application.Network }; } public static Tye.Hosting.Model.EnvironmentVariable ToHostingEnvironmentVariable(this EnvironmentVariableBuilder builder) diff --git a/test/Test.Infrastructure/TestHelpers.cs b/test/Test.Infrastructure/TestHelpers.cs index df520f1b..bf4d3e5d 100644 --- a/test/Test.Infrastructure/TestHelpers.cs +++ b/test/Test.Infrastructure/TestHelpers.cs @@ -251,8 +251,8 @@ namespace Test.Infrastructure var processRunner = new ProcessRunner(logger, replicaRegistry, new ProcessRunnerOptions()); var dockerRunner = new DockerRunner(logger, replicaRegistry); - await processRunner.StartAsync(new Application(new FileInfo(host.Application.Source), new Dictionary(), ContainerEngine.Default)); - await dockerRunner.StartAsync(new Application(new FileInfo(host.Application.Source), new Dictionary(), ContainerEngine.Default)); + await processRunner.StartAsync(new Application(host.Application.Name, new FileInfo(host.Application.Source), new Dictionary(), ContainerEngine.Default)); + await dockerRunner.StartAsync(new Application(host.Application.Name, new FileInfo(host.Application.Source), new Dictionary(), ContainerEngine.Default)); } await DoOperationAndWaitForReplicasToChangeState(host, ReplicaState.Stopped, replicas.Length, replicas.ToHashSet(), new HashSet(), TimeSpan.Zero, Purge);