├── .gitattributes ├── global.json ├── integration-tests ├── global.json ├── NAME.DummyService │ ├── appsettings.json │ ├── Dockerfile │ ├── docker_init.sh │ ├── dependencies.json │ ├── web.config │ ├── Properties │ │ └── launchSettings.json │ ├── Program.cs │ ├── NAME.DummyService.csproj │ └── Startup.cs ├── NAME.DummyConsole.Kestrel │ ├── Dockerfile │ ├── docker_init.sh │ ├── dependencies.json │ ├── NAME.DummyConsole.Kestrel.csproj │ └── Program.cs ├── NAME.IntegrationTests │ ├── Dockerfile │ ├── DummyFilePathMapper.cs │ ├── docker_init.sh │ ├── NAME.IntegrationTests.csproj │ ├── OperatingSystem │ │ └── OperatingSystemVersionResolverTests.cs │ ├── Elasticsearch │ │ └── ElasticsearchVersionResolverTests.cs │ ├── Service │ │ └── SelfHostKestrelServiceVersionResolverTests.cs │ ├── RabbitMq │ │ └── RabbitMqVersionResolverTests.cs │ ├── SqlServer │ │ └── SqlServerVersionResolverTests.cs │ ├── ManifestExplorer │ │ └── ManifestExplorerTests.cs │ └── Constants.cs └── docker-compose.yml ├── tools └── packages.config ├── src ├── NAME │ ├── Nuget │ │ ├── readme.txt │ │ └── Content │ │ │ └── dependencies.json │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Dependencies │ │ ├── Dependency.cs │ │ ├── ConnectedDependency.cs │ │ ├── ServiceDependency.cs │ │ └── OperatingSystemDependency.cs │ ├── SqlServer │ │ └── SqlServerVersions.cs │ ├── ConnectionStrings │ │ ├── StaticConnectionStringProvider.cs │ │ ├── AppSettingsConnectionStringProvider.cs │ │ ├── EnvironmentVariableConnectionStringProvider.cs │ │ └── ConnectionStringsConnectionStringProvider.cs │ ├── ParsedDependencies.cs │ ├── Utils │ │ ├── ResourcesFetcher.cs │ │ └── LogUtils.cs │ ├── OperatingSystem │ │ └── WindowsVersions.cs │ ├── NAME.csproj │ └── ManifestGenerator.cs ├── NAME.WebApi │ ├── Nuget │ │ ├── readme.txt │ │ └── Content │ │ │ └── App_Start │ │ │ └── NAMEConfig.cs.pp │ ├── NAMEConfiguration.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── WebApiFilePathMapper.cs │ ├── NAMEEndpointHttpModule.cs │ ├── NAME.WebApi.csproj │ └── NAMEUiHandler.cs ├── NAME.SelfHost.Kestrel │ ├── Nuget │ │ └── readme.txt │ ├── NAMEKestrelConfiguration.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── NAME.SelfHost.Kestrel.csproj │ ├── ServerStartup.cs │ ├── NAMEServer.cs │ └── KestrelServer.cs ├── NAME.SelfHost.HttpListener │ ├── Nuget │ │ └── readme.txt │ ├── NAMEHttpListenerConfiguration.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── NAME.SelfHost.HttpListener.csproj │ └── NAMEServer.cs ├── NAME.Core │ ├── IFilePathMapper.cs │ ├── DTOs │ │ ├── SendManifestDTO.cs │ │ ├── BootstrapResultDto.cs │ │ └── BootstrapDTO.cs │ ├── NAMEContext.cs │ ├── IVersionResolver.cs │ ├── NAMEStatusLevel.cs │ ├── IConnectionStringProvider.cs │ ├── Utils │ │ ├── Guard.cs │ │ └── SocketHelpers.cs │ ├── SupportedDependencies.cs │ ├── Exceptions │ │ ├── ConnectionStringNotFoundException.cs │ │ ├── DependenciesCheckException.cs │ │ ├── DependencyWithoutNAMEException.cs │ │ ├── VersionParsingException.cs │ │ ├── NAMEException.cs │ │ ├── VersionNotRecognizedException.cs │ │ └── DependencyNotReachableException.cs │ ├── SupportedConnectionStringLocators.cs │ ├── NAME.Core.Shared.shproj │ ├── IVersionTranslator.cs │ ├── SupportedNAMEBehaviours.cs │ ├── Json │ │ ├── IJsonNode.cs │ │ └── SimpleJSONPathValueSystem.cs │ └── Constants.cs ├── NAME.AspNetCore │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── NAMEAspNetCoreConfiguration.cs │ ├── AspNetCoreFilePathMapper.cs │ ├── AspNetCoreConfigurationConnectionStringProvider.cs │ └── NAME.AspNetCore.csproj ├── NAME.SelfHost.Shared │ ├── NAMESelfHostConfigurationExtensions.cs │ ├── StaticFilePathMapper.cs │ ├── ISelfHostServer.cs │ ├── NAME.SelfHost.Shared.projitems │ ├── NAME.SelfHost.Shared.shproj │ ├── NAMESelfHostConfiguration.cs │ └── SelfHostResult.cs ├── NAME.Hosting.Shared │ ├── NAME.Hosting.Shared.projitems │ ├── NAMESettingsExtensions.cs │ ├── NAME.Hosting.Shared.shproj │ └── NAMEBaseConfiguration.cs └── Directory.Build.props ├── unit-tests ├── NAME.Tests │ ├── DummyFilePathMapper.cs │ ├── TestPriorityAttribute.cs │ ├── DummyNotFoundConnectionStringProvider.cs │ ├── Dependencies │ │ ├── StaticVersionResolverMock.cs │ │ └── ConnectedDependencyTests.cs │ ├── MongoDb │ │ └── MongoDbVersionResolverTests.cs │ ├── RabbitMq │ │ └── RabbitMqVersionResolverTests.cs │ ├── ConnectionStrings │ │ ├── ConfigurationManagerHelpers.cs │ │ ├── EnvironmentVariableConnectionStringProviderTests.cs │ │ ├── AppSettingsConnectionStringProviderTests.cs │ │ ├── ConnectionStringsConnectionStringProviderTests.cs │ │ └── JsonPathConnectionStringProviderTests.cs │ ├── Elasticsearch │ │ └── ElasticsearchVersionResolverTests.cs │ ├── PriorityOrder.cs │ ├── SqlServer │ │ ├── SqlServerVersionResolverTests.cs │ │ └── SqlServerVersionTranslatorTests.cs │ ├── NAME.Tests.csproj │ ├── Service │ │ └── ServiceVersionResolverTests.cs │ ├── ManifestGeneratorTests.cs │ ├── Digest │ │ └── Digest.cs │ └── OperatingSystem │ │ └── WindowsVersionTranslatorTests.cs ├── NAME.Hosting.Shared.Tests │ ├── DummyFilePathMapper.cs │ └── NAME.Hosting.Shared.Tests.csproj ├── NAME.WebApi.Tests │ ├── App.config │ ├── Properties │ │ └── AssemblyInfo.cs │ └── NAME.WebApi.Tests.csproj ├── NAME.AspNetCore.Tests │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── NAME.AspNetCore.Tests.csproj │ └── AspNetCoreConfigurationConnectionStringProviderTests.cs ├── NAME.SelfHost.Kestrel.Tests │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── NAMEServerTests.cs │ └── NAME.SelfHost.Kestrel.Tests.csproj └── NAME.SelfHost.HttpListener.Tests │ ├── Properties │ └── AssemblyInfo.cs │ ├── NAME.SelfHost.HttpListener.Tests.csproj │ └── NAMEServerTests.cs ├── .editorconfig ├── stylecop.json ├── .travis.yml ├── appveyor.yml ├── LICENSE ├── CONTRIBUTING.md ├── stylecop.ruleset └── CHANGELOG.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.sh text eol=lf -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "1.0.4" 4 | } 5 | } -------------------------------------------------------------------------------- /integration-tests/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "projects": [ "NAME.IntegrationTests" ], 3 | "sdk": { 4 | "version": "1.1.1" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tools/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /integration-tests/NAME.DummyService/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "TheService": { 3 | "Endpoint": "http://non-existing-fail-dns" 4 | }, 5 | "ConnectionStrings": { 6 | } 7 | } -------------------------------------------------------------------------------- /integration-tests/NAME.DummyService/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/dotnet:1.1.1-sdk 2 | 3 | COPY . /service 4 | 5 | WORKDIR /service 6 | 7 | RUN chmod +x ./docker_init.sh 8 | 9 | EXPOSE 5000/tcp 10 | 11 | CMD ["./docker_init.sh"] 12 | -------------------------------------------------------------------------------- /integration-tests/NAME.DummyConsole.Kestrel/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/dotnet:1.1.1-sdk 2 | 3 | COPY . /service 4 | 5 | WORKDIR /service 6 | 7 | RUN chmod +x ./docker_init.sh 8 | 9 | EXPOSE 40500/tcp 10 | 11 | CMD ["./docker_init.sh"] 12 | -------------------------------------------------------------------------------- /src/NAME/Nuget/readme.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------- 2 | ---- NOS Application Manifest Extension ---- 3 | -------------------------------------------- 4 | 5 | For information on how to configure and use NAME refer to the following page: 6 | https://github.com/nosinovacao/name-sdk -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/DummyFilePathMapper.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | 3 | namespace NAME.Tests 4 | { 5 | public class DummyFilePathMapper : IFilePathMapper 6 | { 7 | public string MapPath(string filePath) 8 | { 9 | return filePath; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/NAME.WebApi/Nuget/readme.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------- 2 | ---- NOS Application Manifest Extension ---- 3 | -------------------------------------------- 4 | 5 | For information on how to configure and use NAME refer to the following page: 6 | https://github.com/nosinovacao/name-sdk -------------------------------------------------------------------------------- /integration-tests/NAME.DummyConsole.Kestrel/docker_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | dotnet restore --source /service/nugets --source https://api.nuget.org/v3/index.json 3 | # Compile before the tests so that the CI reports the build as failed if the tests compilation fails 4 | dotnet build -c Release 5 | 6 | dotnet run 7 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.Kestrel/Nuget/readme.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------- 2 | ---- NOS Application Manifest Extension ---- 3 | -------------------------------------------- 4 | 5 | For information on how to configure and use NAME refer to the following page: 6 | https://github.com/nosinovacao/name-sdk -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | end_of_line = crlf 4 | indent_style = space:warning 5 | indent_size = 4 6 | charset = utf-8 7 | 8 | [*.xml] 9 | indent_style = space 10 | 11 | [*.json] 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.cs] 16 | csharp_style_inlined_variable_declaration = true:warning -------------------------------------------------------------------------------- /src/NAME.SelfHost.HttpListener/Nuget/readme.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------- 2 | ---- NOS Application Manifest Extension ---- 3 | -------------------------------------------- 4 | 5 | For information on how to configure and use NAME refer to the following page: 6 | https://github.com/nosinovacao/name-sdk -------------------------------------------------------------------------------- /integration-tests/NAME.DummyService/docker_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | dotnet restore --source /service/nugets --source https://api.nuget.org/v3/index.json 3 | # Compile before the tests so that the CI reports the build as failed if the tests compilation fails 4 | dotnet build -c Release 5 | 6 | dotnet run --server.urls http://*:5000 7 | -------------------------------------------------------------------------------- /unit-tests/NAME.Hosting.Shared.Tests/DummyFilePathMapper.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | 3 | namespace NAME.Hosting.Shared.Tests 4 | { 5 | public class DummyFilePathMapper : IFilePathMapper 6 | { 7 | public string MapPath(string filePath) 8 | { 9 | return filePath; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /integration-tests/NAME.IntegrationTests/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/dotnet:1.1.1-sdk 2 | WORKDIR /integration 3 | COPY . ./ 4 | # COPY ../../Output/Artifacts/NuGets/Release ./nugets 5 | # RUN dotnet restore 6 | RUN chmod +x ./docker_init.sh 7 | RUN chmod +x ./multi-wait-for-it.sh 8 | ENV OPERATING_SYSTEM=debian 9 | 10 | CMD ["./docker_init.sh"] -------------------------------------------------------------------------------- /integration-tests/NAME.DummyConsole.Kestrel/dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "infrastructure_dependencies": [ 3 | 4 | ], 5 | "service_dependencies": [ 6 | { 7 | "name": "DummyService", 8 | "connection_string": "http://dummy-service:5000/manifest", 9 | "min_version": "0.0.0", 10 | "max_version": "9.9.9" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /integration-tests/NAME.DummyService/dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "infrastructure_dependencies": [ 3 | 4 | ], 5 | "service_dependencies": [ 6 | { 7 | "name": "The Service", 8 | "min_version": "1.2.53", 9 | "max_version": "1.8", 10 | "connection_string": { 11 | "locator": "IConfiguration", 12 | "key": "TheService:Endpoint" 13 | } 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/TestPriorityAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NAME.Tests 4 | { 5 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] 6 | public class TestPriorityAttribute : Attribute 7 | { 8 | public TestPriorityAttribute(int priority) 9 | { 10 | Priority = priority; 11 | } 12 | 13 | public int Priority { get; private set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/DummyNotFoundConnectionStringProvider.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace NAME.Tests 8 | { 9 | public class DummyNotFoundConnectionStringProvider : IConnectionStringProvider 10 | { 11 | public bool TryGetConnectionString(out string connectionString) 12 | { 13 | connectionString = null; 14 | return false; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /stylecop.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 3 | "settings": { 4 | "maintainabilityRules": { 5 | "topLevelTypes": ["class", "interface", "struct", "enum"] 6 | }, 7 | "documentationRules": { 8 | "companyName": "NOS Inovação", 9 | "copyrightText": "Copyright (c) {companyName}. All rights reserved.", 10 | "documentationCulture": "en-GB" 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/NAME.Core/IFilePathMapper.cs: -------------------------------------------------------------------------------- 1 | namespace NAME.Core 2 | { 3 | /// 4 | /// Provides a mechanism to map relative file paths to absolute paths. 5 | /// 6 | public interface IFilePathMapper 7 | { 8 | /// 9 | /// Maps the specified path to an absolute path. 10 | /// 11 | /// The relative file path. 12 | /// Returns the absolute file path. 13 | string MapPath(string filePath); 14 | } 15 | } -------------------------------------------------------------------------------- /src/NAME.Core/DTOs/SendManifestDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NAME.DTOs 6 | { 7 | /// 8 | /// Represents a data transfer object for the manifest. 9 | /// 10 | public class SendManifestDTO 11 | { 12 | /// 13 | /// Gets or sets the manifest. 14 | /// 15 | /// 16 | /// The manifest. 17 | /// 18 | public string Manifest { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.Kestrel/NAMEKestrelConfiguration.cs: -------------------------------------------------------------------------------- 1 | using NAME.Hosting.Shared; 2 | using NAME.SelfHost.Shared; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Threading.Tasks; 8 | 9 | namespace NAME.SelfHost.Kestrel 10 | { 11 | /// 12 | /// Represents the configuration for NAME. 13 | /// 14 | /// 15 | public class NAMEKestrelConfiguration : NAMESelfHostConfiguration 16 | { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | branches: 3 | only: 4 | - master 5 | - dev 6 | os: 7 | - linux 8 | # .NET CLI require Ubuntu 14.04 9 | dist: trusty 10 | services: 11 | - docker 12 | # Ensure that .NET Core is installed 13 | dotnet: 1.0.4 14 | # Ensure Mono is installed 15 | mono: latest 16 | env: 17 | # Set the DOTNET_SKIP_FIRST_TIME_EXPERIENCE environment variable to stop wasting time caching packages 18 | # Disable sending usage data to Microsoft 19 | - DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true DOTNET_CLI_TELEMETRY_OPTOUT=true 20 | script: 21 | - ./build.sh -t TravisCI -------------------------------------------------------------------------------- /src/NAME.SelfHost.HttpListener/NAMEHttpListenerConfiguration.cs: -------------------------------------------------------------------------------- 1 | using NAME.Hosting.Shared; 2 | using NAME.SelfHost.Shared; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace NAME.SelfHost.HttpListener 9 | { 10 | /// 11 | /// Represents the configuration to be used for the 12 | /// 13 | /// 14 | public class NAMEHttpListenerConfiguration : NAMESelfHostConfiguration 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/NAME.Core/NAMEContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NAME.Core 6 | { 7 | /// 8 | /// Represents the current NAME context. 9 | /// 10 | public class NAMEContext 11 | { 12 | /// 13 | /// Gets or sets the service dependency current number of hops. 14 | /// 15 | /// 16 | /// The service dependency current number of hops. 17 | /// 18 | public int ServiceDependencyCurrentNumberOfHops { get; set; } = 0; 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /integration-tests/NAME.DummyService/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/NAME.Core/IVersionResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.Core 7 | { 8 | /// 9 | /// Provides a mechanism to resolve the version of a service. 10 | /// 11 | public interface IVersionResolver // where TVersion : DependencyVersion 12 | { 13 | /// 14 | /// Gets the versions. 15 | /// 16 | /// Returns a task that represents the asynchronous operation. The result contains an enumerable with the versions. 17 | Task> GetVersions(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /unit-tests/NAME.WebApi.Tests/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/NAME.Core/NAMEStatusLevel.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | 3 | namespace NAME 4 | { 5 | /// 6 | /// Represents the status level of a NAME operation. 7 | /// Ordered by level of severity. 8 | /// 9 | public enum NAMEStatusLevel 10 | { 11 | /// 12 | /// No errors were found. 13 | /// 14 | Ok = 0, 15 | 16 | /// 17 | /// The status of a dependency could not be resolved. E.g.: NAME not installed. 18 | /// 19 | Warn = 10, 20 | 21 | /// 22 | /// The status of a dependency was successfully resolved and is not valid. 23 | /// 24 | Error = 20 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/Dependencies/StaticVersionResolverMock.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace NAME.Tests.Dependencies 8 | { 9 | public class StaticVersionResolverMock : IVersionResolver 10 | { 11 | private IEnumerable versionsToReturn; 12 | public StaticVersionResolverMock(IEnumerable versionsToReturn) 13 | { 14 | this.versionsToReturn = versionsToReturn; 15 | } 16 | 17 | public Task> GetVersions() 18 | { 19 | return Task.FromResult(versionsToReturn); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/NAME.WebApi/NAMEConfiguration.cs: -------------------------------------------------------------------------------- 1 | using NAME.Hosting.Shared; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Threading.Tasks; 7 | using System.Web; 8 | using System.Web.Http; 9 | 10 | namespace NAME.WebApi 11 | { 12 | /// 13 | /// Represents the configuration for NAME. 14 | /// 15 | public class NAMEConfiguration : NAMEBaseConfiguration 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | public NAMEConfiguration() 21 | { 22 | this.DependenciesFilePath = "~/dependencies.json"; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/NAME.WebApi/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | // Setting ComVisible to false makes the types in this assembly not visible 10 | // to COM components. If you need to access a type in this assembly from 11 | // COM, set the ComVisible attribute to true on that type. 12 | [assembly: ComVisible(false)] 13 | 14 | // The following GUID is for the ID of the typelib if this project is exposed to COM 15 | [assembly: Guid("23b5dafc-d49f-41b5-ab84-b9bae9578cc4")] 16 | -------------------------------------------------------------------------------- /src/NAME.AspNetCore/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | // Setting ComVisible to false makes the types in this assembly not visible 10 | // to COM components. If you need to access a type in this assembly from 11 | // COM, set the ComVisible attribute to true on that type. 12 | [assembly: ComVisible(false)] 13 | 14 | // The following GUID is for the ID of the typelib if this project is exposed to COM 15 | [assembly: Guid("f5d256a5-56df-45f1-a2aa-1b366e6bc5ea")] 16 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.Kestrel/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | // Setting ComVisible to false makes the types in this assembly not visible 10 | // to COM components. If you need to access a type in this assembly from 11 | // COM, set the ComVisible attribute to true on that type. 12 | [assembly: ComVisible(false)] 13 | 14 | // The following GUID is for the ID of the typelib if this project is exposed to COM 15 | [assembly: Guid("bd5d9f86-bf08-4d53-a3be-99e3f9f06db4")] 16 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.HttpListener/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | // Setting ComVisible to false makes the types in this assembly not visible 10 | // to COM components. If you need to access a type in this assembly from 11 | // COM, set the ComVisible attribute to true on that type. 12 | [assembly: ComVisible(false)] 13 | 14 | // The following GUID is for the ID of the typelib if this project is exposed to COM 15 | [assembly: Guid("eabdc739-41ab-493f-a3a7-60bcd5be9c7a")] 16 | -------------------------------------------------------------------------------- /src/NAME.Core/IConnectionStringProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.Core 7 | { 8 | /// 9 | /// Contract for connection string providers to implement. 10 | /// 11 | public interface IConnectionStringProvider 12 | { 13 | /// 14 | /// Gets the connection string. 15 | /// 16 | /// A containing the connection string. 17 | /// 18 | /// Returns true if the connection string was fetched successfully. 19 | /// 20 | bool TryGetConnectionString(out string connectionString); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.Shared/NAMESelfHostConfigurationExtensions.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace NAME.SelfHost.Shared 7 | { 8 | internal static class NAMESelfHostConfigurationExtensions 9 | { 10 | public static string GetRelativeManifestPath(this NAMESelfHostConfiguration configuration) 11 | { 12 | string normalizedPrefix = string.Empty; 13 | 14 | if (!string.IsNullOrWhiteSpace(configuration.ManifestUriPrefix) && configuration.ManifestUriPrefix != "/") 15 | normalizedPrefix = '/' + configuration.ManifestUriPrefix.TrimStart('/').TrimEnd('/'); 16 | 17 | return normalizedPrefix + Constants.MANIFEST_ENDPOINT; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /integration-tests/NAME.DummyService/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:1479/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "launchUrl": "api/values", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "NAME.DummyService": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "launchUrl": "http://localhost:5000/api/values", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/NAME.Hosting.Shared/NAME.Hosting.Shared.projitems: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 1b69400b-f2b5-417a-9234-5f12114554a8 7 | 8 | 9 | NAME.Hosting.Shared 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/NAME/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: InternalsVisibleTo("NAME.Tests")] 9 | [assembly: InternalsVisibleTo("NAME.IntegrationTests")] 10 | 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("50ab471c-4769-4c65-a219-dbd9d8389c6c")] 19 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/MongoDb/MongoDbVersionResolverTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using NAME.Core.Exceptions; 3 | using NAME.MongoDb; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using Xunit; 9 | 10 | namespace NAME.Tests.MongoDb 11 | { 12 | public class MongoDbVersionResolverTests 13 | { 14 | [Fact] 15 | [Trait("TestCategory", "Unit")] 16 | public async Task GetVersions_ConnectionStringNotFound() 17 | { 18 | IVersionResolver resolver = new MongoDbVersionResolver(new DummyNotFoundConnectionStringProvider(),10,10); 19 | 20 | await Assert.ThrowsAsync(async () => 21 | { 22 | var value = await resolver.GetVersions().ConfigureAwait(false); 23 | }); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/RabbitMq/RabbitMqVersionResolverTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using NAME.Core.Exceptions; 3 | using NAME.RabbitMq; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using Xunit; 9 | 10 | namespace NAME.Tests.RabbitMq 11 | { 12 | public class RabbitMqVersionResolverTests 13 | { 14 | [Fact] 15 | [Trait("TestCategory", "Unit")] 16 | public async Task GetVersions_ConnectionStringNotFound() 17 | { 18 | IVersionResolver resolver = new RabbitMqVersionResolver(new DummyNotFoundConnectionStringProvider(), 10000, 10000); 19 | 20 | await Assert.ThrowsAsync(async () => 21 | { 22 | var value = await resolver.GetVersions().ConfigureAwait(false); 23 | }); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/NAME.Core/Utils/Guard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NAME.Core.Utils 4 | { 5 | /// 6 | /// Provides methods to guard values. 7 | /// 8 | public static class Guard 9 | { 10 | /// 11 | /// Checks the value for nullity. 12 | /// 13 | /// The type of the value 14 | /// The value. 15 | /// The name. 16 | /// The value. 17 | /// Throws the exception when the value is null. 18 | public static TValue NotNull(TValue value, string name) 19 | { 20 | if (value == null) 21 | throw new ArgumentNullException(name); 22 | return value; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/NAME.Hosting.Shared/NAMESettingsExtensions.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace NAME.Hosting.Shared 7 | { 8 | /// 9 | /// Provides extension methods for . 10 | /// 11 | public static class NAMESettingsExtensions 12 | { 13 | /// 14 | /// Determines if the manifest endpoint should be enabled considering the current state. 15 | /// 16 | /// The NAME settings. 17 | /// Returns true if the endpoint should be enabled. 18 | public static bool IsManifestEndpointEnabled(this NAMESettings nameSettings) 19 | { 20 | return nameSettings.RunningMode != SupportedNAMEBehaviours.NAMEDisabled; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/NAME.Core/SupportedDependencies.cs: -------------------------------------------------------------------------------- 1 | namespace NAME.Core 2 | { 3 | /// 4 | /// Represents all the supported dependencies. 5 | /// 6 | public enum SupportedDependencies 7 | { 8 | /// 9 | /// MongoDb 10 | /// 11 | MongoDb = 10, 12 | 13 | /// 14 | /// Operating System 15 | /// 16 | OperatingSystem = 20, 17 | 18 | /// 19 | /// RabbitMq 20 | /// 21 | RabbitMq = 30, 22 | 23 | /// 24 | /// SQL Server 25 | /// 26 | SqlServer = 40, 27 | 28 | /// 29 | /// A service with NAME 30 | /// 31 | Service = 50, 32 | 33 | /// 34 | /// Elasticsearch 35 | /// 36 | Elasticsearch = 60 37 | } 38 | } -------------------------------------------------------------------------------- /src/NAME.SelfHost.Shared/StaticFilePathMapper.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace NAME.SelfHost.Shared 10 | { 11 | /// 12 | /// Provides a file path mapper for static paths. 13 | /// 14 | /// 15 | public class StaticFilePathMapper : IFilePathMapper 16 | { 17 | /// 18 | /// Maps the specified path to an absolute path. 19 | /// 20 | /// The relative file path. 21 | /// 22 | /// Returns the absolute file path. 23 | /// 24 | public string MapPath(string filePath) 25 | { 26 | return Path.Combine(Directory.GetCurrentDirectory(), filePath); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /unit-tests/NAME.WebApi.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("Microsoft Corporation")] 10 | [assembly: AssemblyProduct("NAME.WebApi.Tests")] 11 | [assembly: AssemblyTrademark("")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("88b50ff9-a480-4a9b-a5f9-c9e4a79e098c")] 20 | -------------------------------------------------------------------------------- /src/NAME.Core/Exceptions/ConnectionStringNotFoundException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.Core.Exceptions 7 | { 8 | /// 9 | /// Represents an exception for when the connection string could not be found. 10 | /// 11 | /// 12 | public class ConnectionStringNotFoundException : NAMEException 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | /// The provider used to try to get the connection string. 18 | public ConnectionStringNotFoundException(string provider) 19 | : base($"Unable to find the connection string using: {provider}.", NAMEStatusLevel.Warn) 20 | { 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /integration-tests/NAME.IntegrationTests/DummyFilePathMapper.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace NAME.IntegrationTests 10 | { 11 | /// 12 | /// Provides a file path mapper for static paths. 13 | /// 14 | /// 15 | public class DummyFilePathMapper : IFilePathMapper 16 | { 17 | /// 18 | /// Maps the specified path to an absolute path. 19 | /// 20 | /// The relative file path. 21 | /// 22 | /// Returns the absolute file path. 23 | /// 24 | public string MapPath(string filePath) 25 | { 26 | return Path.Combine(Directory.GetCurrentDirectory(), filePath); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /unit-tests/NAME.AspNetCore.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("Microsoft Corporation")] 10 | [assembly: AssemblyProduct("NAME.AspNetCore.Tests")] 11 | [assembly: AssemblyTrademark("")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("6b27cd9b-cdd8-425b-9fad-e4eef18a8ee6")] 20 | -------------------------------------------------------------------------------- /integration-tests/NAME.DummyConsole.Kestrel/NAME.DummyConsole.Kestrel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp1.1 5 | true 6 | NAME.DummyConsole.Kestrel 7 | Exe 8 | NAME.DummyConsole.Kestrel 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | PreserveNewest 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /unit-tests/NAME.SelfHost.Kestrel.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("Microsoft Corporation")] 10 | [assembly: AssemblyProduct("NAME.SelfHost.Kestrel.Tests")] 11 | [assembly: AssemblyTrademark("")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("6b27cd9b-cdd8-425b-9fad-e4eef18a8ee6")] 20 | -------------------------------------------------------------------------------- /unit-tests/NAME.SelfHost.HttpListener.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("Microsoft Corporation")] 10 | [assembly: AssemblyProduct("NAME.SelfHost.HttpListener.Tests")] 11 | [assembly: AssemblyTrademark("")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("6b27cd9b-cdd8-425b-9fad-e4eef18a8ee6")] 20 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/ConnectionStrings/ConfigurationManagerHelpers.cs: -------------------------------------------------------------------------------- 1 | #if NET452 2 | using System.Configuration; 3 | using System.Reflection; 4 | using System.Collections.Specialized; 5 | 6 | namespace NAME.Tests.ConnectionStrings 7 | { 8 | public static class ConfigurationManagerHelpers 9 | { 10 | public static NameValueCollection SetWritable(this NameValueCollection collection) 11 | { 12 | typeof(NameObjectCollectionBase).GetProperty("IsReadOnly", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(collection, false, null); 13 | return collection; 14 | } 15 | 16 | public static T SetWritable(this T collection) where T : ConfigurationElementCollection 17 | { 18 | var fi = typeof(ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic); 19 | fi.SetValue(collection, false); 20 | return collection; 21 | } 22 | } 23 | } 24 | #endif -------------------------------------------------------------------------------- /integration-tests/NAME.DummyService/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.Builder; 8 | using Microsoft.Extensions.Configuration; 9 | 10 | namespace NAME.DummyService 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | var config = new ConfigurationBuilder() 17 | .AddCommandLine(args) 18 | .AddEnvironmentVariables(prefix: "ASPNETCORE_") 19 | .Build(); 20 | 21 | var host = new WebHostBuilder() 22 | .UseConfiguration(config) 23 | .UseKestrel() 24 | .UseContentRoot(Directory.GetCurrentDirectory()) 25 | .UseIISIntegration() 26 | .UseStartup() 27 | .Build(); 28 | 29 | host.Run(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/NAME.AspNetCore/NAMEAspNetCoreConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using NAME.Hosting.Shared; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace NAME.AspNetCore 9 | { 10 | /// 11 | /// Represents the configuration used for NAME in a ASP.NET core environment. 12 | /// 13 | /// 14 | public class NAMEAspNetCoreConfiguration : NAMEBaseConfiguration 15 | { 16 | /// 17 | /// Gets or sets the Asp.Net Core configuration instance to be used by NAME. 18 | /// 19 | public IConfiguration Configuration { get; set; } 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | public NAMEAspNetCoreConfiguration() 25 | { 26 | this.DependenciesFilePath = "dependencies.json"; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/NAME.Core/SupportedConnectionStringLocators.cs: -------------------------------------------------------------------------------- 1 | namespace NAME.Core 2 | { 3 | /// 4 | /// Represents the supported connection string locators. 5 | /// 6 | public enum SupportedConnectionStringLocators 7 | { 8 | #if NET45 9 | /// 10 | /// ConfigurationManager ConnectionStrings. 11 | /// 12 | ConnectionStrings = 10, 13 | 14 | /// 15 | /// ConfigurationManager AppSettings. 16 | /// 17 | AppSettings = 20, 18 | 19 | /// 20 | /// Visual Studio generated settings file. 21 | /// 22 | VSSettingsFile = 30, 23 | #endif 24 | 25 | /// 26 | /// JsonPath. 27 | /// 28 | JSONPath = 40, 29 | 30 | /// 31 | /// XPath. 32 | /// 33 | XPath = 50, 34 | 35 | /// 36 | /// EnvironmentVariable 37 | /// 38 | EnvironmentVariable = 60 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.Shared/ISelfHostServer.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace NAME.SelfHost.Shared 7 | { 8 | /// 9 | /// Provides mechanisms for handling the SelfHost servers. 10 | /// 11 | /// 12 | internal interface ISelfHostServer : IDisposable 13 | { 14 | /// 15 | /// Gets the port of the server. 16 | /// 17 | /// 18 | /// The port where the server is listening for connections. 19 | /// 20 | int? Port { get; } 21 | 22 | /// 23 | /// Starts the server. 24 | /// 25 | /// The port. 26 | /// The settings. 27 | /// 28 | /// Returns true if the server is successfully started. Else returns false. 29 | /// 30 | bool Start(int port, NAMESettings settings); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/NAME.WebApi/WebApiFilePathMapper.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Threading.Tasks; 8 | using System.Web.Hosting; 9 | 10 | namespace NAME.WebApi 11 | { 12 | internal class WebApiFilePathMapper : IFilePathMapper 13 | { 14 | public string MapPath(string filePath) 15 | { 16 | if (filePath == null) 17 | return null; 18 | 19 | string path = null; 20 | if (filePath.StartsWith("~") || filePath.StartsWith("\\") || filePath.StartsWith("/")) 21 | path = HostingEnvironment.MapPath(filePath); 22 | 23 | // path is null if this is a self host environment (e.g. OWIN). 24 | if (path == null) 25 | { 26 | var uriPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; 27 | path = Path.Combine(new Uri(uriPath).LocalPath, filePath); 28 | } 29 | 30 | return path; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/NAME.SelfHost.Shared/NAME.SelfHost.Shared.projitems: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | b7f1edf7-131e-494d-a7ce-f6d3d994a8b2 7 | 8 | 9 | NAME.SelfHost.Shared 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/NAME.Core/NAME.Core.Shared.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6bed7e20-a9a1-41e1-9a74-fd1c9211d181 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/NAME.Core/IVersionTranslator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.Core 7 | { 8 | /// 9 | /// Represents a contract to translate an object to a DependencyVersion. 10 | /// 11 | ///// The type of the version output. 12 | public interface IVersionTranslator 13 | { 14 | /// 15 | /// Translates the specified string to a TVersion. 16 | /// 17 | /// The source string. 18 | /// Returns a TVersion that identifies the specified source. 19 | DependencyVersion Translate(string source); 20 | 21 | /// 22 | /// Translates the specified TVersion of an object of type T. 23 | /// 24 | /// The source TVersion. 25 | /// Returns an instance of type T. 26 | string Translate(DependencyVersion source); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/NAME.Hosting.Shared/NAME.Hosting.Shared.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1b69400b-f2b5-417a-9234-5f12114554a8 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/NAME/Dependencies/Dependency.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using NAME.Core; 6 | using NAME.Core.Exceptions; 7 | using NAME.Json; 8 | 9 | namespace NAME.Dependencies 10 | { 11 | /// 12 | /// A Dependency 13 | /// 14 | public abstract class Dependency 15 | { 16 | /// 17 | /// Determines the dependency status. 18 | /// 19 | /// Returns a task that represents the asynchronous operation. The result contains the status of the dependency. 20 | public abstract Task GetStatus(); 21 | 22 | /// 23 | /// Gets the manifest representation of this instance in JSON format. 24 | /// 25 | /// 26 | /// Returns a task that represents the asynchronous operation. The result contains a that represents this instance manifest representation in JSON format. 27 | /// 28 | internal abstract Task ToJson(); 29 | } 30 | } -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/Dependencies/ConnectedDependencyTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using NAME.Dependencies; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using Xunit; 8 | 9 | namespace NAME.Tests.Dependencies 10 | { 11 | public class ConnectedDependencyTests 12 | { 13 | [Fact] 14 | [Trait("TestCategory", "Unit")] 15 | public async Task WithoutShowingConnectionString() 16 | { 17 | var versionResolver = new StaticVersionResolverMock(new[] { new DependencyVersion(1, 0, 0) }); 18 | ConnectedDependency dependency = new ConnectedDependency(versionResolver) 19 | { 20 | MinimumVersion = new DependencyVersion(0, 0, 1), 21 | MaximumVersion = new DependencyVersion(9, 9, 9), 22 | Name = "Test", 23 | ShowConnectionStringInJson = false, 24 | Type = SupportedDependencies.Service 25 | }; 26 | var result = await dependency.ToJson(); 27 | 28 | Assert.Null(result["value"]); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.Shared/NAME.SelfHost.Shared.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | b7f1edf7-131e-494d-a7ce-f6d3d994a8b2 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/NAME.Core/DTOs/BootstrapResultDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.Core.DTOs 7 | { 8 | /// 9 | /// Represents the result of a bootstrap service operation 10 | /// 11 | public class BootstrapResultDto 12 | { 13 | /// 14 | /// Gets or sets the protocol to be used for subsequent operations. 15 | /// 16 | /// 17 | /// The protocol to be used for subsequent operations. 18 | /// 19 | public uint Protocol { get; set; } 20 | 21 | /// 22 | /// Gets or sets the session identifier. 23 | /// 24 | /// 25 | /// The session identifier. 26 | /// 27 | public string SessionId { get; set; } 28 | 29 | /// 30 | /// Gets or sets the overrides. 31 | /// 32 | /// 33 | /// The overrides. 34 | /// 35 | public NAMESettings Overrides { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/NAME.Core/SupportedNAMEBehaviours.cs: -------------------------------------------------------------------------------- 1 | namespace NAME.Core 2 | { 3 | /// 4 | /// Represents the supported NAME behaviours 5 | /// 6 | public enum SupportedNAMEBehaviours 7 | { 8 | /// 9 | /// The standard behaviour. Provides full NAME functionality. 10 | /// 11 | Standard = 0, 12 | 13 | /// 14 | /// The reporting disabled behaviour. Provides the funcionationalilies in EXCEPT reporting the manifest to registry. 15 | /// 16 | AnnounceDisabled = 1, 17 | 18 | /// 19 | /// The heartbeat disabled behaviour. Will register it self with the Registry on application startup but will not heartbeat it's status. 20 | /// 21 | HeartbeatDisabled = 2, 22 | 23 | /// 24 | /// The announce disabled behaviour. Will not announce it self with the Registry. 25 | /// 26 | BootstrapDisabled = 3, 27 | 28 | /// 29 | /// The name disabled behaviour. Will not provide any NAME functionality. 30 | /// 31 | NAMEDisabled = 4 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /integration-tests/NAME.IntegrationTests/docker_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | dotnet restore --source /integration/nugets --source https://api.nuget.org/v3/index.json 3 | # Compile before the tests so that the CI reports the build as failed if the tests compilation fails 4 | dotnet build -c Release 5 | 6 | errorCode=$? 7 | if [ $errorCode -ne 0 ] 8 | then 9 | printf "Build failed." 10 | exit $errorCode 11 | fi 12 | 13 | # This should be replace by Docker Healthcheck s when docker-compose adds support for it 14 | ./multi-wait-for-it.sh $SPECIFIC_RABBIT_HOSTNAME:5672 $LATEST_RABBIT_HOSTNAME:5672 $SPECIFIC_MONGO_HOSTNAME:27017 $LATEST_MONGO_HOSTNAME:27017 $SPECIFIC_SERVICE_HOSTNAME:5000 $LATEST_SQLSERVER_HOSTNAME:1433 $SPECIFIC_KESTREL_SELFHOST_HOSTNAME:40500 -t 120 15 | 16 | errorCode=$? 17 | if [ $errorCode -ne 0 ] 18 | then 19 | printf "ERROR: The dependencies containers did not start in the expected timeout." 20 | exit $errorCode 21 | fi 22 | 23 | # We do not need to exit with an error code on tests failing, the CI will look for the tests report file mark the build FAILED if it does not exist. 24 | dotnet test -c Release --no-build --logger "trx;LogFileName=/integration/TestResults/integrationTests.trx" --filter "TestCategory=Integration" -------------------------------------------------------------------------------- /src/NAME/Dependencies/ConnectedDependency.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using NAME.Json; 7 | 8 | namespace NAME.Dependencies 9 | { 10 | /// 11 | /// Dependency with a version resolver and a connectionString 12 | /// 13 | /// 14 | internal class ConnectedDependency : VersionedDependency 15 | { 16 | public ConnectedDependency(IVersionResolver versionResolver) 17 | : base(versionResolver) 18 | { 19 | } 20 | 21 | public bool ShowConnectionStringInJson { get; set; } 22 | 23 | public IConnectionStringProvider ConnectionStringProvider { get; set; } 24 | 25 | internal override async Task ToJson() 26 | { 27 | JsonNode node = await base.ToJson().ConfigureAwait(false); 28 | if (this.ShowConnectionStringInJson) 29 | { 30 | string connectionString = string.Empty; 31 | if (this.ConnectionStringProvider?.TryGetConnectionString(out connectionString) == true) 32 | node.Add("value", connectionString); 33 | } 34 | return node; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /integration-tests/NAME.DummyConsole.Kestrel/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NAME.SelfHost.Kestrel; 3 | using System.Reflection; 4 | using System.Threading; 5 | 6 | namespace NAME.DummyConsole 7 | { 8 | class Program 9 | { 10 | private static readonly AutoResetEvent _closing = new AutoResetEvent(false); 11 | 12 | static void Main(string[] args) 13 | { 14 | Action configBuilder = config => 15 | { 16 | Assembly a = typeof(Program).GetTypeInfo().Assembly; 17 | config.APIName = a.GetName().Name; 18 | config.APIVersion = a.GetName().Version.ToString(); 19 | config.LogHealthCheckToConsole = true; 20 | config.ThrowOnDependenciesFail = false; 21 | }; 22 | 23 | using (var selfHost = NAMEServer.EnableName(configBuilder)) 24 | { 25 | Console.WriteLine("Hello World!"); 26 | 27 | Console.CancelKeyPress += new ConsoleCancelEventHandler(OnExit); 28 | _closing.WaitOne(); 29 | } 30 | } 31 | 32 | protected static void OnExit(object sender, ConsoleCancelEventArgs args) 33 | { 34 | Console.WriteLine("Exiting"); 35 | _closing.Set(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NAME/Dependencies/ServiceDependency.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using NAME.Core; 3 | using NAME.Json; 4 | 5 | namespace NAME.Dependencies 6 | { 7 | /// 8 | /// Represents an external service dependency 9 | /// 10 | /// 11 | internal class ServiceDependency : ConnectedDependency 12 | { 13 | public ServiceDependency(IVersionResolver versionResolver) 14 | : base(versionResolver) 15 | { 16 | } 17 | 18 | internal JsonNode Manifest { get; private set; } 19 | 20 | internal override async Task ToJson() 21 | { 22 | JsonNode node = await base.ToJson(); 23 | if (this.Manifest != null) 24 | { 25 | JsonNode infrastructureDependencies = this.Manifest["infrastructure_dependencies"]; 26 | JsonNode serviceDependencies = this.Manifest["service_dependencies"]; 27 | 28 | if (infrastructureDependencies != null) 29 | node.Add("infrastructure_dependencies", infrastructureDependencies); 30 | if (serviceDependencies != null) 31 | node.Add("service_dependencies", serviceDependencies); 32 | } 33 | return node; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/Elasticsearch/ElasticsearchVersionResolverTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.ConnectionStrings; 2 | using NAME.Core; 3 | using NAME.Core.Exceptions; 4 | using NAME.Elasticsearch; 5 | using System.Threading.Tasks; 6 | using Xunit; 7 | 8 | namespace NAME.Tests.Elasticsearch 9 | { 10 | public class ElasticsearchVersionResolverTests 11 | { 12 | [Fact] 13 | [Trait("TestCategory", "Unit")] 14 | public async Task GetVersions_ConnectionStringNotFound() 15 | { 16 | IVersionResolver resolver = new ElasticsearchVersionResolver(new DummyNotFoundConnectionStringProvider(), 10, 10); 17 | 18 | await Assert.ThrowsAsync(async () => 19 | { 20 | var value = await resolver.GetVersions().ConfigureAwait(false); 21 | }); 22 | } 23 | 24 | [Fact] 25 | [Trait("TestCategory", "Unit")] 26 | public async Task GetVersions_DependencyNotReachable() 27 | { 28 | IVersionResolver resolver = new ElasticsearchVersionResolver(new StaticConnectionStringProvider(""), 10, 10); 29 | 30 | await Assert.ThrowsAsync(async () => 31 | { 32 | var value = await resolver.GetVersions().ConfigureAwait(false); 33 | }); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/NAME.AspNetCore/AspNetCoreFilePathMapper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using NAME.Core; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace NAME.AspNetCore 8 | { 9 | /// 10 | /// Provides a path mapper for Asp.Net Core 11 | /// 12 | /// 13 | public class AspNetCoreFilePathMapper : IFilePathMapper 14 | { 15 | private IHostingEnvironment environment; 16 | 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// The environment. 21 | public AspNetCoreFilePathMapper(IHostingEnvironment environment) 22 | { 23 | this.environment = environment; 24 | } 25 | 26 | /// 27 | /// Maps the specified path to an absolute path. 28 | /// 29 | /// The relative file path. 30 | /// 31 | /// Returns the absolute file path. 32 | /// 33 | public string MapPath(string filePath) 34 | { 35 | return System.IO.Path.Combine(this.environment.ContentRootPath ?? string.Empty, filePath); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.Kestrel/NAME.SelfHost.Kestrel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Provides a way to add NAME as a self host web api endpoint for .NET core using the Kestrel web-server. 5 | Miguel Alexandre;João Trigo Soares 6 | netstandard1.6 7 | true 8 | NAME.SelfHost.Kestrel 9 | NAME.SelfHost.Kestrel 10 | NOS NAME Self Host SelfHost Kestrel NOS Api Manifest Extension 11 | $(PackageTargetFallback);dnxcore50 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | true 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/NAME/SqlServer/SqlServerVersions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.SqlServer 7 | { 8 | /// 9 | /// The possible SQL Server versions. 10 | /// 11 | public enum SqlServerVersions 12 | { 13 | /// 14 | /// The SQL Server 7.0 15 | /// 16 | SqlServer7, 17 | 18 | /// 19 | /// The SQL Server 2000 20 | /// 21 | SqlServer2000, 22 | 23 | /// 24 | /// The SQL Server 2005 25 | /// 26 | SqlServer2005, 27 | 28 | /// 29 | /// The SQL Server 2008 30 | /// 31 | SqlServer2008, 32 | 33 | /// 34 | /// The SQL Server 2008 R2 35 | /// 36 | SqlServer2008R2, 37 | 38 | /// 39 | /// The SQL Server 2012 40 | /// 41 | SqlServer2012, 42 | 43 | /// 44 | /// The SQL Server 2014 45 | /// 46 | SqlServer2014, 47 | 48 | /// 49 | /// The SQL Server 2016 50 | /// 51 | SqlServer2016 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /unit-tests/NAME.Hosting.Shared.Tests/NAME.Hosting.Shared.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp1.0;net452 5 | portable 6 | NAME.Hosting.Shared.Tests 7 | NAME.Hosting.Shared.Tests 8 | true 9 | $(PackageTargetFallback);dotnet5.4;portable-net451+win8 10 | 1.1.1 11 | 12 | false 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/NAME.WebApi/NAMEEndpointHttpModule.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using System.Web; 9 | 10 | namespace NAME.WebApi 11 | { 12 | /// 13 | /// Provides a mechanism to add the NAME endpoint as a custom header to all Web Api responses. 14 | /// 15 | internal class NAMEEndpointHttpModule : IHttpModule 16 | { 17 | #pragma warning disable SA1401 18 | internal static string NameEndpoint = null; 19 | #pragma warning restore SA1401 20 | 21 | public void Dispose() 22 | { 23 | } 24 | 25 | public void Init(HttpApplication context) 26 | { 27 | // This only works if running in IIS7+ Integrated Pipeline mode 28 | if (!HttpRuntime.UsingIntegratedPipeline) 29 | return; 30 | 31 | context.PreSendRequestHeaders += this.Context_PreSendRequestHeaders; 32 | } 33 | 34 | private void Context_PreSendRequestHeaders(object sender, EventArgs e) 35 | { 36 | var app = sender as HttpApplication; 37 | if (app != null && app.Context != null) 38 | { 39 | app.Context.Response.AppendHeader(Constants.MANIFEST_ENDPOINT_HEADER_NAME, NameEndpoint); 40 | } 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.Kestrel/ServerStartup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Primitives; 7 | using NAME.AspNetCore; 8 | using NAME.Core; 9 | using NAME.Hosting.Shared; 10 | using NAME.SelfHost.Shared; 11 | using System; 12 | using System.Collections.Generic; 13 | using System.Diagnostics; 14 | using System.Linq; 15 | using System.Net; 16 | using System.Threading.Tasks; 17 | using static NAME.Hosting.Shared.DependenciesUtils; 18 | 19 | namespace NAME.SelfHost.Kestrel 20 | { 21 | internal class ServerStartup 22 | { 23 | 24 | // This method gets called by the runtime. Use this method to add services to the container. 25 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | } 29 | 30 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 31 | public void Configure(IApplicationBuilder app, IFilePathMapper pathMapper, NAMEKestrelConfiguration configuration, NAMESettings settings) 32 | { 33 | app.UseMiddleware(configuration, settings, pathMapper); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.HttpListener/NAME.SelfHost.HttpListener.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Provides a way to add NAME as a self host web api endpoint for .NET using the HttpListener. 5 | Miguel Alexandre;João Trigo Soares 6 | net45 7 | true 8 | NAME.SelfHost.HttpListener 9 | NAME.SelfHost.HttpListener 10 | NOS NAME Self Host HttpListener WebApi NOS Api Manifest Extension 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | true 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/NAME.AspNetCore/AspNetCoreConfigurationConnectionStringProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using NAME.Core; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace NAME.AspNetCore 8 | { 9 | internal class AspNetCoreConfigurationConnectionStringProvider : IConnectionStringProvider 10 | { 11 | private readonly IConfiguration configuration; 12 | private readonly string connectionStringKey; 13 | 14 | public AspNetCoreConfigurationConnectionStringProvider(IConfiguration configuration, string connectionStringKey) 15 | { 16 | if (string.IsNullOrWhiteSpace(connectionStringKey)) 17 | { 18 | throw new ArgumentException("Value must be set.", nameof(connectionStringKey)); 19 | } 20 | 21 | this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); 22 | this.connectionStringKey = connectionStringKey; 23 | } 24 | 25 | public bool TryGetConnectionString(out string connectionString) 26 | { 27 | try 28 | { 29 | connectionString = this.configuration[this.connectionStringKey]; 30 | return connectionString != null; 31 | } 32 | catch 33 | { 34 | connectionString = null; 35 | return false; 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{branch}-{build}' 2 | branches: 3 | only: 4 | - master 5 | - dev 6 | nuget: 7 | # Do not publish NuGet packages for pull requests 8 | disable_publish_on_pr: true 9 | environment: 10 | # Set the DOTNET_SKIP_FIRST_TIME_EXPERIENCE environment variable to stop wasting time caching packages 11 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 12 | # Disable sending usage data to Microsoft 13 | DOTNET_CLI_TELEMETRY_OPTOUT: true 14 | # Use init to set the version using the Directory.Build.props file, branch and build number 15 | on_finish: 16 | - ps: | 17 | $versionPrefix = ([xml](Get-Content .\src\Directory.Build.props)).Project.PropertyGroup.VersionPrefix 18 | Update-AppveyorBuild -Version "$versionPrefix-$env:APPVEYOR_REPO_BRANCH-$env:APPVEYOR_BUILD_NUMBER" 19 | build_script: 20 | - ps: .\build.ps1 -t AppVeyor --nugetPreReleaseTag="beta$env:APPVEYOR_BUILD_NUMBER" 21 | test: off 22 | artifacts: 23 | # Store NuGet packages 24 | - path: .\Output\Artifacts\NuGets\PreRelease\*.nupkg 25 | name: NuGet-PreRelease 26 | # Store NuGet packages 27 | - path: .\Output\Artifacts\NuGets\Release\*.nupkg 28 | name: NuGet-Release 29 | deploy: 30 | - provider: Environment 31 | name: name-sdk-nuget-pre-release 32 | on: 33 | branch: master 34 | appveyor_repo_tag: false 35 | # Use the manual deployment in appveyor to release a stable nuget package. 36 | # - provider: Environment 37 | # name: name-sdk-nuget-release 38 | # on: 39 | # appveyor_repo_tag: true -------------------------------------------------------------------------------- /integration-tests/NAME.IntegrationTests/NAME.IntegrationTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp1.0 5 | portable 6 | NAME.IntegrationTests 7 | NAME.IntegrationTests 8 | true 9 | $(PackageTargetFallback);dotnet5.4;portable-net451+win8 10 | 1.1.1 11 | false 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/NAME.Core/Exceptions/DependenciesCheckException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.Core.Exceptions 7 | { 8 | /// 9 | /// Represents an exception that happens when the dependencies checks fail. 10 | /// 11 | /// 12 | public class DependenciesCheckException : AggregateException 13 | { 14 | /// 15 | /// Gets the dependencies statutes. 16 | /// 17 | /// 18 | /// The dependencies statutes. 19 | /// 20 | public IEnumerable DependenciesStatutes { get; } 21 | 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | /// The dependencies statuses. 26 | public DependenciesCheckException(IEnumerable dependenciesStatuses) 27 | : base(string.Join(Environment.NewLine, dependenciesStatuses.Where(s => s.CheckStatus != NAMEStatusLevel.Ok).Select(s => s.Message)), dependenciesStatuses.Where(d => d.CheckStatus != NAMEStatusLevel.Ok && d.InnerException != null).Select(d => d.InnerException)) 28 | { 29 | this.DependenciesStatutes = dependenciesStatuses; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /integration-tests/NAME.IntegrationTests/OperatingSystem/OperatingSystemVersionResolverTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using NAME.OperatingSystem; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Threading.Tasks; 8 | using Xunit; 9 | 10 | namespace NAME.IntegrationTests.OperatingSystem 11 | { 12 | public class OperatingSystemVersionResolverTests 13 | { 14 | [Fact] 15 | [Trait("TestCategory", "Integration")] 16 | public async Task GetVersions_NoException() 17 | { 18 | IVersionResolver resolver = new OperatingSystemVersionResolver(); 19 | 20 | var versions = await resolver.GetVersions().ConfigureAwait(false); 21 | 22 | Assert.Equal(1, versions.Count()); 23 | Assert.True(versions.First() < new DependencyVersion(9999, 9999, 9999)); 24 | Assert.True(versions.First() > new DependencyVersion(0, 0, 0)); 25 | Assert.IsType(versions.First()); 26 | Assert.False(string.IsNullOrEmpty(((OperatingSystemDependencyVersion)versions.First()).OperatingSystem), "The Operating System should not be null."); 27 | Assert.Equal(((OperatingSystemDependencyVersion)versions.First()).OperatingSystem, Constants.ExpectedOperatingSystem); 28 | //Assert.True(versions.First().OperatingSystem == "ubuntu" || versions.First().OperatingSystem == "windows"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/NAME/ConnectionStrings/StaticConnectionStringProvider.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace NAME.ConnectionStrings 8 | { 9 | /// 10 | /// Represents an object that returns always the same connection string. 11 | /// 12 | /// 13 | public class StaticConnectionStringProvider : IConnectionStringProvider 14 | { 15 | private string connectionString; 16 | 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// The connection string. 21 | public StaticConnectionStringProvider(string connectionString) 22 | { 23 | this.connectionString = connectionString; 24 | } 25 | 26 | /// 27 | /// Gets the connection string. 28 | /// 29 | /// A containing the connection string. 30 | /// 31 | /// Returns true if the connection string was fetched successfully. 32 | /// 33 | public bool TryGetConnectionString(out string connectionString) 34 | { 35 | connectionString = this.connectionString; 36 | return true; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/NAME/ParsedDependencies.cs: -------------------------------------------------------------------------------- 1 | using NAME.Dependencies; 2 | using System.Collections.Generic; 3 | 4 | namespace NAME 5 | { 6 | /// 7 | /// A NAME Configuration 8 | /// 9 | public class ParsedDependencies 10 | { 11 | /// 12 | /// Gets the infrastructure dependencies. 13 | /// 14 | /// 15 | /// The infrastructure dependencies. 16 | /// 17 | public IEnumerable InfrastructureDependencies { get; private set; } 18 | 19 | /// 20 | /// Gets the service dependencies. 21 | /// 22 | /// 23 | /// The service dependencies. 24 | /// 25 | public IEnumerable ServiceDependencies { get; private set; } 26 | 27 | /// 28 | /// Initializes a new instance of the class. 29 | /// 30 | /// The infrastructure dependencies. 31 | /// The service dependencies. 32 | public ParsedDependencies(IList infrastructureDependencies, IList serviceDependencies) 33 | { 34 | this.InfrastructureDependencies = infrastructureDependencies ?? new List(); 35 | this.ServiceDependencies = serviceDependencies ?? new List(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NAME.WebApi/NAME.WebApi.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Provides a way to seamlessly add NAME to a WebApi project. 5 | Miguel Alexandre;João Trigo Soares 6 | net45 7 | true 8 | NAME.WebApi 9 | NAME.WebApi 10 | NOS NAME WebApi NOS Api Manifest Extension 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | true 19 | 20 | 21 | Content\App_Start 22 | true 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/NAME.WebApi/NAMEUiHandler.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net.Http; 7 | using System.Net.Http.Headers; 8 | using System.Reflection; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | using NAME.Core.Utils; 12 | using NAME.Utils; 13 | using NAME.Hosting.Shared; 14 | using System.Net; 15 | 16 | namespace NAME.WebApi 17 | { 18 | internal class NAMEUiHandler : HttpMessageHandler 19 | { 20 | private volatile string cachedHtml = null; 21 | private readonly NAMESettings settings; 22 | 23 | public NAMEUiHandler(NAMESettings settings) 24 | { 25 | this.settings = settings; 26 | } 27 | 28 | protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 29 | { 30 | if (!this.settings.IsManifestEndpointEnabled()) 31 | return new HttpResponseMessage(HttpStatusCode.NotFound); 32 | 33 | string manifestLink = request.GetUrlHelper().Route("NAME_Manifest", new { }); 34 | 35 | if (this.cachedHtml == null) 36 | this.cachedHtml = await ResourcesFetcher.GetNAMEUiAsync(manifestLink); 37 | 38 | var content = new StringContent(this.cachedHtml); 39 | 40 | content.Headers.ContentType = new MediaTypeHeaderValue("text/html"); 41 | 42 | return new HttpResponseMessage { Content = content }; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/NAME.AspNetCore/NAME.AspNetCore.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Provides a way to seamlessly add NAME to a Asp.Net Core project. 5 | netstandard1.6;net451 6 | true 7 | NAME.AspNetCore 8 | NAME.AspNetCore 9 | $(PackageTargetFallback);dnxcore50 10 | 11 | 12 | 13 | 14 | 15 | 16 | All 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/ConnectionStrings/EnvironmentVariableConnectionStringProviderTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | using NAME.Core; 4 | using NAME.ConnectionStrings; 5 | 6 | 7 | namespace NAME.Tests.ConnectionStrings 8 | { 9 | public class EnvironmentVariableConnectionStringProviderTests 10 | { 11 | 12 | [Fact] 13 | [Trait("TestCategory", "Unit")] 14 | public void TryGetConnectionString() 15 | { 16 | string key = "ConnectionStrings_Accounts-MongoDb"; 17 | string connString = "mongodb://some-mongo-instance:27017/some-db"; 18 | Environment.SetEnvironmentVariable(key, connString); 19 | IConnectionStringProvider provider = new EnvironmentVariableConnectionStringProvider(key); 20 | bool result = provider.TryGetConnectionString(out string outConnection); 21 | 22 | Assert.True(result, "Environment variable not found"); 23 | Assert.Equal(outConnection, connString); 24 | } 25 | 26 | [Fact] 27 | [Trait("TestCategory", "Unit")] 28 | public void TryGetConnectionString_NotFound() 29 | { 30 | string key = "ConnectionStrings_Accounts-MongoDb_nonexistant"; 31 | IConnectionStringProvider provider = new EnvironmentVariableConnectionStringProvider(key); 32 | bool result = provider.TryGetConnectionString(out string outConnection); 33 | 34 | Assert.False(result, "The connection string should not be found."); 35 | Assert.Null(outConnection); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NAME.Core/Exceptions/DependencyWithoutNAMEException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NAME.Core.Exceptions 6 | { 7 | /// 8 | /// Happens when a dependency does not have NAME installed. 9 | /// 10 | /// 11 | public class DependencyWithoutNAMEException : NAMEException 12 | { 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// The message that represents the error. 17 | /// Inner exception. 18 | public DependencyWithoutNAMEException(string message, Exception inner) 19 | : base(message, inner, NAMEStatusLevel.Warn) 20 | { 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | /// Inner exception. 27 | public DependencyWithoutNAMEException(Exception inner) 28 | : this($"Dependency does not have NAME installed!", inner) 29 | { 30 | 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class. 35 | /// 36 | public DependencyWithoutNAMEException() 37 | : this(null) 38 | { 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, NOS Inovação 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /src/NAME.Core/Exceptions/VersionParsingException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.Core.Exceptions 7 | { 8 | /// 9 | /// Happens when parsing of an invalid version. 10 | /// 11 | /// 12 | public class VersionParsingException : NAMEException 13 | { 14 | /// 15 | /// Gets the version attempted to parse. 16 | /// 17 | /// 18 | /// The version attempted to parse. 19 | /// 20 | public string SourceVersion { get; private set; } 21 | 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | /// The source version. 26 | /// The message. 27 | public VersionParsingException(string sourceVersion, string message) 28 | : base(message, NAMEStatusLevel.Warn) 29 | { 30 | this.SourceVersion = sourceVersion; 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class. 35 | /// 36 | /// The source version. 37 | public VersionParsingException(string sourceVersion) 38 | : this(sourceVersion, $"The provided version {sourceVersion} is invalid.") 39 | { 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/NAME/Nuget/Content/dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/nosinovacao/name-sdk/schema-v1/name.dependencies.v1.jschema", 3 | //Use this file to define all your application dependencies. 4 | "infrastructure_dependencies": [ 5 | //{ 6 | // "os_name": "Windows", 7 | // "type": "OperatingSystem", 8 | // "min_version": "WindowsServer2008R2", 9 | // "max_version": "*" 10 | //}, 11 | //{ 12 | // "type": "MongoDb", 13 | // "min_version": "2.6", 14 | // "max_version": "3.2", 15 | // "connection_string": { 16 | // "locator": "ConnectionStrings", 17 | // "key": "MongoDBConnectionString" 18 | // } 19 | //}, 20 | //{ 21 | // "type": "RabbitMq", 22 | // "name": "rabbitmq", 23 | // "min_version": "3.0.0", 24 | // "max_version": "3.6.5", 25 | // "connection_string": { 26 | // "locator": "ConnectionStrings", 27 | // "key": "EventaConnectionString" 28 | // } 29 | //}, 30 | //{ 31 | // "type": "Elasticsearch", 32 | // "min_version": "5.5.1", 33 | // "max_version": "5.6.3", 34 | // "connection_string": { 35 | // "locator": "ConnectionStrings", 36 | // "key": "ElasticConnectionString" 37 | // } 38 | //} 39 | ], 40 | "service_dependencies": [ 41 | //{ 42 | // "name": "AAAA", 43 | // "min_version": "2.3.7", 44 | // "max_version": "3.1.2", 45 | // "connection_string": { 46 | // "locator": "VSSettingsFile", 47 | // "section": "nPVR.Services.AAAAClient.Properties.Settings", 48 | // "key": "AAAAEndpoint" 49 | // } 50 | //} 51 | ] 52 | } -------------------------------------------------------------------------------- /unit-tests/NAME.SelfHost.HttpListener.Tests/NAME.SelfHost.HttpListener.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452 5 | portable 6 | NAME.SelfHost.HttpListener.Tests 7 | NAME.SelfHost.HttpListener.Tests 8 | true 9 | false 10 | false 11 | false 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Net.Http.dll 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /integration-tests/NAME.IntegrationTests/Elasticsearch/ElasticsearchVersionResolverTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.ConnectionStrings; 2 | using NAME.Core; 3 | using NAME.Core.Utils; 4 | using NAME.Elasticsearch; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using Xunit; 8 | 9 | namespace NAME.IntegrationTests.Elasticsearch 10 | { 11 | public class ElasticsearchVersionResolverTests 12 | { 13 | [Fact] 14 | [Trait("TestCategory", "Integration")] 15 | public async Task GetVersions_SpecificVersion() 16 | { 17 | ElasticsearchVersionResolver resolver = new ElasticsearchVersionResolver(new StaticConnectionStringProvider($"http://{ Constants.SpecificElasticsearchHostname }:9200"), 10000, 10000); 18 | 19 | var versions = await resolver.GetVersions().ConfigureAwait(false); 20 | 21 | Assert.Equal(1, versions.Count()); 22 | Assert.Equal(versions.First(), DependencyVersionParser.Parse(Constants.SpecificElasticsearchVersion, false)); 23 | } 24 | 25 | [Fact] 26 | [Trait("TestCategory", "Integration")] 27 | public async Task GetVersions_LatestVersion() 28 | { 29 | ElasticsearchVersionResolver resolver = new ElasticsearchVersionResolver(new StaticConnectionStringProvider($"http://{ Constants.LatestElasticsearchHostname }:9200"), 10000, 10000); 30 | 31 | var versions = await resolver.GetVersions().ConfigureAwait(false); 32 | 33 | Assert.Equal(1, versions.Count()); 34 | // Latest GA RELEASE: https://www.elastic.co/downloads/elasticsearch#ga-release 35 | Assert.Equal(versions.First(), DependencyVersionParser.Parse("5.6.3", false)); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /unit-tests/NAME.SelfHost.HttpListener.Tests/NAMEServerTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using Xunit; 6 | using System.IO; 7 | using System.Net; 8 | using NAME.SelfHost.Shared; 9 | using System.Net.Http; 10 | 11 | namespace NAME.SelfHost.HttpListener.Tests 12 | { 13 | public class NAMEServerTests 14 | { 15 | 16 | [Fact] 17 | [Trait("TestCategory", "Unit")] 18 | public async Task ManifestUI_ReturnsRelativeURL() 19 | { 20 | string fileName = Directory.GetCurrentDirectory() + @"\" + Guid.NewGuid().ToString() + ".json"; 21 | 22 | SelfHostResult server = null; 23 | HttpClient client = new HttpClient(); 24 | 25 | try 26 | { 27 | File.WriteAllText(fileName, "{ }"); 28 | server = NAMEServer.EnableName((config) => 29 | { 30 | config.LogHealthCheckToConsole = false; 31 | config.APIName = "teste"; 32 | config.APIVersion = "1.0.0"; 33 | config.DependenciesFilePath = fileName; 34 | }); 35 | 36 | var response = await client.GetAsync($"http://localhost:{server.ServerPort}/manifest/ui"); 37 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 38 | 39 | Assert.Contains("loadfromURL(\"/manifest\");", await response.Content.ReadAsStringAsync()); 40 | } 41 | finally 42 | { 43 | server?.Dispose(); 44 | client.Dispose(); 45 | File.Delete(fileName); 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /unit-tests/NAME.SelfHost.Kestrel.Tests/NAMEServerTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using NAME.SelfHost.Kestrel; 6 | using Xunit; 7 | using System.IO; 8 | using System.Net.Http; 9 | using System.Net; 10 | using NAME.SelfHost.Shared; 11 | 12 | namespace NAME.SelfHost.Kestrel.Tests 13 | { 14 | public class NAMEServerTests 15 | { 16 | 17 | [Fact] 18 | [Trait("TestCategory", "Unit")] 19 | public async Task ManifestUI_ReturnsRelativeURL() 20 | { 21 | string fileName = Directory.GetCurrentDirectory() + @"\" + Guid.NewGuid().ToString() + ".json"; 22 | 23 | SelfHostResult server = null; 24 | HttpClient client = new HttpClient(); 25 | 26 | try 27 | { 28 | File.WriteAllText(fileName, "{ }"); 29 | server = NAMEServer.EnableName((config) => 30 | { 31 | config.LogHealthCheckToConsole = false; 32 | config.APIName = "teste"; 33 | config.APIVersion = "1.0.0"; 34 | config.DependenciesFilePath = fileName; 35 | }); 36 | 37 | var response = await client.GetAsync($"http://localhost:{server.ServerPort}/manifest/ui"); 38 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 39 | 40 | Assert.Contains("loadfromURL(\"/manifest\");", await response.Content.ReadAsStringAsync()); 41 | } 42 | finally 43 | { 44 | server?.Dispose(); 45 | client.Dispose(); 46 | File.Delete(fileName); 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/PriorityOrder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Xunit.Abstractions; 6 | using Xunit.Sdk; 7 | 8 | namespace NAME.Tests 9 | { 10 | public class PriorityOrderer : ITestCaseOrderer 11 | { 12 | public IEnumerable OrderTestCases(IEnumerable testCases) where TTestCase : ITestCase 13 | { 14 | var sortedMethods = new SortedDictionary>(); 15 | 16 | foreach (TTestCase testCase in testCases) 17 | { 18 | int priority = 0; 19 | 20 | foreach (IAttributeInfo attr in testCase.TestMethod.Method.GetCustomAttributes((typeof(TestPriorityAttribute).AssemblyQualifiedName))) 21 | priority = attr.GetNamedArgument("Priority"); 22 | 23 | GetOrCreate(sortedMethods, priority).Add(testCase); 24 | } 25 | 26 | foreach (var list in sortedMethods.Keys.Select(priority => sortedMethods[priority])) 27 | { 28 | list.Sort((x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.TestMethod.Method.Name, y.TestMethod.Method.Name)); 29 | foreach (TTestCase testCase in list) 30 | yield return testCase; 31 | } 32 | } 33 | 34 | static TValue GetOrCreate(IDictionary dictionary, TKey key) where TValue : new() 35 | { 36 | TValue result; 37 | 38 | if (dictionary.TryGetValue(key, out result)) return result; 39 | 40 | result = new TValue(); 41 | dictionary[key] = result; 42 | 43 | return result; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1.2.1 5 | $(VersionPrefix) 6 | NOS Inovação 7 | NOS NAME NOS Api Manifest Extension name nos api manifest extension 8 | https://github.com/nosinovacao/name-sdk 9 | Check https://github.com/nosinovacao/name-sdk/blob/master/CHANGELOG.md for release notes. 10 | true 11 | ../../stylecop.ruleset 12 | NOS Inovação 13 | Copyright © NOS Inovação 2016-$([System.DateTime]::UtcNow.Year) 14 | https://github.com/nosinovacao/name-sdk/blob/master/LICENSE 15 | true 16 | true 17 | true 18 | true 19 | 20 | 21 | 22 | 23 | All 24 | 25 | 26 | 27 | 28 | 29 | 30 | <_Parameter1>$(MSBuildProjectName).Tests 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/SqlServer/SqlServerVersionResolverTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.ConnectionStrings; 2 | using NAME.Core; 3 | using NAME.Core.Exceptions; 4 | using NAME.MongoDb; 5 | using NAME.SqlServer; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | using Xunit; 11 | 12 | namespace NAME.Tests.SqlServer 13 | { 14 | public class SqlServerVersionResolverTests 15 | { 16 | [Fact] 17 | [Trait("TestCategory", "Unit")] 18 | public async Task GetVersions_WrongPort() 19 | { 20 | string connectionString = "metadata = res://*/ProfilePreferences.csdl|res://*/ProfilePreferences.ssdl|res://*/ProfilePreferences.msl;provider=System.Data.SqlClient;provider connection string=\"Data Source=10.149.194.64,65535;initial catalog=NosProfilePreferencesManagerV2_TST;user id=userProfileSettingsDB;password=userProfileSettings;MultipleActiveResultSets=True;App=EntityFramework\""; 21 | IVersionResolver resolver = new SqlServerVersionResolver(new StaticConnectionStringProvider(connectionString), 10000, 10000); 22 | 23 | await Assert.ThrowsAsync(async () => 24 | { 25 | var value = await resolver.GetVersions().ConfigureAwait(false); 26 | }); 27 | } 28 | 29 | [Fact] 30 | [Trait("TestCategory", "Unit")] 31 | public async Task GetVersions_ConnectionStringNotFound() 32 | { IVersionResolver resolver = new SqlServerVersionResolver(new DummyNotFoundConnectionStringProvider(), 10000, 10000); 33 | 34 | await Assert.ThrowsAsync(async () => 35 | { 36 | var value = await resolver.GetVersions().ConfigureAwait(false); 37 | }); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/NAME.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netcoreapp1.0 5 | portable 6 | NAME.Tests 7 | NAME.Tests 8 | true 9 | $(PackageTargetFallback);dotnet5.4;portable-net451+win8 10 | 1.1.1 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /unit-tests/NAME.WebApi.Tests/NAME.WebApi.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452 5 | portable 6 | NAME.WebApi.Tests 7 | NAME.WebApi.Tests 8 | true 9 | false 10 | false 11 | false 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.Kestrel/NAMEServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using NAME.Core; 8 | using NAME.Core.Exceptions; 9 | using NAME.Dependencies; 10 | using NAME.Hosting.Shared; 11 | using NAME.SelfHost.Shared; 12 | using static NAME.Utils.LogUtils; 13 | 14 | namespace NAME.SelfHost.Kestrel 15 | { 16 | /// 17 | /// Provides a mechanism to start a self hosted HTTP server serving the NAME endpoints using the Kestrel server. 18 | /// 19 | public static class NAMEServer 20 | { 21 | /// 22 | /// Enables the NAME self host server. 23 | /// 24 | /// The name configuration builder. 25 | /// Returns an proxy object containing the Parsed Dependencies and a way to stop the server. 26 | /// Error parsing the dependencies file. 27 | /// Happens when is set to true and dependencies check fail. 28 | public static SelfHostResult EnableName(Action nameConfigBuilder) 29 | { 30 | var config = new NAMEKestrelConfiguration(); 31 | nameConfigBuilder?.Invoke(config); 32 | 33 | var pathMapper = new StaticFilePathMapper(); 34 | 35 | var server = new KestrelServer(config, pathMapper); 36 | var parsedDependencies = SelfHostInitializer.Initialize(server, pathMapper, config); 37 | 38 | return new SelfHostResult(parsedDependencies, server); 39 | } 40 | 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/NAME.Core/Exceptions/NAMEException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.Core.Exceptions 7 | { 8 | /// 9 | /// Represents a generic NAME exception. 10 | /// 11 | /// 12 | public class NAMEException : Exception 13 | { 14 | /// 15 | /// Gets or sets the status level of the operation that originated this exception. 16 | /// 17 | /// 18 | /// The status level of the operation that originated this exception. 19 | /// 20 | public NAMEStatusLevel StatusLevel { get; set; } 21 | 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | /// The message that describes the error. 26 | /// The status level of the operation that originated this exception. 27 | public NAMEException(string message, NAMEStatusLevel statusLevel) 28 | : base(message) 29 | { 30 | this.StatusLevel = statusLevel; 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class. 35 | /// 36 | /// The message that describes the error. 37 | /// The inner exception. 38 | /// The status level of the operation that originated this exception. 39 | public NAMEException(string message, Exception inner, NAMEStatusLevel statusLevel) 40 | : base(message, inner) 41 | { 42 | this.StatusLevel = statusLevel; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /unit-tests/NAME.SelfHost.Kestrel.Tests/NAME.SelfHost.Kestrel.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp1.0 5 | portable 6 | NAME.SelfHost.Kestrel.Tests 7 | NAME.SelfHost.Kestrel.Tests 8 | $(PackageTargetFallback);dotnet5.4;portable-net451+win8 9 | 1.1.1 10 | true 11 | false 12 | false 13 | false 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/ConnectionStrings/AppSettingsConnectionStringProviderTests.cs: -------------------------------------------------------------------------------- 1 | #if NET452 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Xunit; 7 | using NAME.Core; 8 | using NAME.ConnectionStrings; 9 | using System.Configuration; 10 | using System.Collections.Specialized; 11 | using System.Reflection; 12 | 13 | namespace NAME.Tests.ConnectionStrings 14 | { 15 | public class AppSettingsConnectionStringProviderTests 16 | { 17 | 18 | [Fact] 19 | [Trait("TestCategory", "Unit")] 20 | public void TryGetConnectionString() 21 | { 22 | string key = "TheAllMightyKey"; 23 | string connString = "mongodb://some-mongo-instance:27017/some-db"; 24 | ConfigurationManager.AppSettings.SetWritable()[key] = connString; 25 | IConnectionStringProvider provider = new AppSettingsConnectionStringProvider(key); 26 | bool result = provider.TryGetConnectionString(out string outConnection); 27 | 28 | Assert.True(result, "Unable to get the connection string."); 29 | Assert.Equal(outConnection, connString); 30 | } 31 | 32 | [Fact] 33 | [Trait("TestCategory", "Unit")] 34 | public void TryGetConnectionString_NotFound() 35 | { 36 | string key = "TheSecondAllMightyKey"; 37 | string connString = "mongodb://some-mongo-instance:27017/some-db"; 38 | ConfigurationManager.AppSettings.SetWritable()[key + "Thou shall not find it!"] = connString; 39 | IConnectionStringProvider provider = new AppSettingsConnectionStringProvider(key); 40 | bool result = provider.TryGetConnectionString(out string outConnection); 41 | 42 | Assert.False(result, "The connection string should not be found."); 43 | Assert.Null(outConnection); 44 | } 45 | } 46 | } 47 | #endif -------------------------------------------------------------------------------- /src/NAME.Core/DTOs/BootstrapDTO.cs: -------------------------------------------------------------------------------- 1 | namespace NAME.Core.DTOs 2 | { 3 | /// 4 | /// Represents a data transfer object for the service. 5 | /// 6 | public class BootstrapDTO 7 | { 8 | 9 | /// 10 | /// Gets or sets the supported protocols. 11 | /// 12 | /// 13 | /// The supported protocols. 14 | /// 15 | public uint[] SupportedProtocols { get; set; } 16 | 17 | /// 18 | /// Gets or sets the hostname. 19 | /// 20 | /// 21 | /// The hostname. 22 | /// 23 | public string Hostname { get; set; } 24 | 25 | /// 26 | /// Gets or sets the name endpoint. 27 | /// 28 | /// 29 | /// The name endpoint. 30 | /// 31 | public string NAMEEndpoint { get; set; } 32 | 33 | /// 34 | /// Gets or sets the NAME port. 35 | /// 36 | /// 37 | /// The NAME port. 38 | /// 39 | public uint? NAMEPort { get; set; } 40 | 41 | /// 42 | /// Gets or sets the name of the application. 43 | /// 44 | /// 45 | /// The name of the application. 46 | /// 47 | public string AppName { get; set; } 48 | 49 | /// 50 | /// Gets or sets the application version. 51 | /// 52 | /// 53 | /// The application version. 54 | /// 55 | public string AppVersion { get; set; } 56 | 57 | /// 58 | /// Gets or sets the NAME version. 59 | /// 60 | /// 61 | /// The name version. 62 | /// 63 | public string NAMEVersion { get; set; } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/NAME/Utils/ResourcesFetcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Threading.Tasks; 7 | 8 | namespace NAME.Utils 9 | { 10 | /// 11 | /// Provides ways to fetch resourcess from the NAME assembly. 12 | /// 13 | public static class ResourcesFetcher 14 | { 15 | private const string MANIFEST_LINK_PLACEHOLDER = "[MANIFEST_LINK_PLACEHOLDER]"; 16 | 17 | /// 18 | /// Gets the NAME UI HTML page. 19 | /// 20 | /// The manifest URL. 21 | /// Returns the HTML page for the NAME UI. 22 | public static async Task GetNAMEUiAsync(string manifestUrl) 23 | { 24 | using (Stream s = typeof(ResourcesFetcher).GetTypeInfo().Assembly.GetManifestResourceStream("NAME.Resources.NAME_UI.html")) 25 | using (StreamReader reader = new StreamReader(s)) 26 | { 27 | string tempHtml = await reader.ReadToEndAsync(); 28 | return tempHtml.Replace(MANIFEST_LINK_PLACEHOLDER, manifestUrl); 29 | } 30 | } 31 | 32 | /// 33 | /// Gets the NAME UI HTML page. 34 | /// 35 | /// The manifest URL. 36 | /// Returns the HTML page for the NAME UI. 37 | public static string GetNAMEUi(string manifestUrl) 38 | { 39 | using (Stream s = typeof(ResourcesFetcher).GetTypeInfo().Assembly.GetManifestResourceStream("NAME.Resources.NAME_UI.html")) 40 | using (StreamReader reader = new StreamReader(s)) 41 | { 42 | string tempHtml = reader.ReadToEnd(); 43 | return tempHtml.Replace(MANIFEST_LINK_PLACEHOLDER, manifestUrl); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.Shared/NAMESelfHostConfiguration.cs: -------------------------------------------------------------------------------- 1 | using NAME.Hosting.Shared; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace NAME.SelfHost.Shared 7 | { 8 | // Disable this error, the types will be coming from the same assembly anyway. 9 | // TODO: When this project is ported to the new SDK tooling (.csproj) migrate the shared code projects to code library in order to fix this. 10 | #pragma warning disable CS0436 // Type conflicts with imported type 11 | 12 | /// 13 | /// Represents the configuration used for NAME SelfHosting. 14 | /// 15 | public class NAMESelfHostConfiguration : NAMEBaseConfiguration 16 | #pragma warning restore CS0436 // Type conflicts with imported type 17 | { 18 | /// 19 | /// Gets or sets the adress where the server will listen for connections. 20 | /// By default it is "*", meaning it will bind to all IPs. 21 | /// 22 | /// 23 | /// The address where the server will listen for connections. 24 | /// 25 | public string AddressToListenOn { get; set; } 26 | 27 | /// 28 | /// Gets or sets a value indicating whether the initial health check should to logged to the console. 29 | /// 30 | /// 31 | /// true if the initial health check should to logged to the console; otherwise, false. 32 | /// 33 | public bool LogHealthCheckToConsole { get; set; } 34 | 35 | /// 36 | /// Initializes a new instance of the class. 37 | /// 38 | public NAMESelfHostConfiguration() 39 | { 40 | this.AddressToListenOn = "*"; 41 | this.DependenciesFilePath = "./dependencies.json"; 42 | this.LogHealthCheckToConsole = false; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/ConnectionStrings/ConnectionStringsConnectionStringProviderTests.cs: -------------------------------------------------------------------------------- 1 | #if NET452 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Xunit; 7 | using NAME.Core; 8 | using NAME.ConnectionStrings; 9 | using System.Configuration; 10 | using System.Reflection; 11 | 12 | namespace NAME.Tests.ConnectionStrings 13 | { 14 | public class ConnectionStringsConnectionStringProviderTests 15 | { 16 | 17 | [Fact] 18 | [Trait("TestCategory", "Unit")] 19 | public void TryGetConnectionString() 20 | { 21 | string key = "TheAllMightyKey"; 22 | string connString = "mongodb://some-mongo-instance:27017/some-db"; 23 | 24 | ConfigurationManager.ConnectionStrings.SetWritable().Add(new ConnectionStringSettings(key, connString)); 25 | IConnectionStringProvider provider = new ConnectionStringsConnectionStringProvider(key); 26 | bool result = provider.TryGetConnectionString(out string outConnection); 27 | 28 | Assert.True(result, "Unable to get the connection string."); 29 | Assert.Equal(outConnection, connString); 30 | } 31 | 32 | [Fact] 33 | [Trait("TestCategory", "Unit")] 34 | public void TryGetConnectionString_NotFound() 35 | { 36 | string key = "TheSecondAllMightyKey"; 37 | string connString = "mongodb://some-mongo-instance:27017/some-db"; 38 | ConfigurationManager.ConnectionStrings.SetWritable().Add(new ConnectionStringSettings(key + "Thou shall not find it!", connString)); 39 | IConnectionStringProvider provider = new ConnectionStringsConnectionStringProvider(key); 40 | bool result = provider.TryGetConnectionString(out string outConnection); 41 | 42 | Assert.False(result, "The connection string should not be found."); 43 | Assert.Null(outConnection); 44 | } 45 | } 46 | } 47 | #endif -------------------------------------------------------------------------------- /src/NAME/ConnectionStrings/AppSettingsConnectionStringProvider.cs: -------------------------------------------------------------------------------- 1 | #if NET45 2 | using NAME.Core; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Configuration; 8 | 9 | namespace NAME.ConnectionStrings 10 | { 11 | /// 12 | /// Provides a mechanism to fetch connection strings from the AppSettings. 13 | /// 14 | /// 15 | public class AppSettingsConnectionStringProvider : IConnectionStringProvider 16 | { 17 | 18 | private string key; 19 | 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | /// The key of the connection string. 24 | public AppSettingsConnectionStringProvider(string key) 25 | { 26 | this.key = key; 27 | } 28 | 29 | /// 30 | /// Gets the connection string. 31 | /// 32 | /// A containing the connection string.. 33 | /// Returns true if the connection string was fetched successfully. 34 | public bool TryGetConnectionString(out string connectionString) 35 | { 36 | connectionString = ConfigurationManager.AppSettings[this.key]; 37 | return connectionString != null; 38 | } 39 | 40 | /// 41 | /// Returns a that represents this instance. 42 | /// 43 | /// 44 | /// A that represents this instance. 45 | /// 46 | public override string ToString() 47 | { 48 | return $"Locator: {SupportedConnectionStringLocators.AppSettings}, Key: {this.key}"; 49 | } 50 | } 51 | } 52 | #endif -------------------------------------------------------------------------------- /src/NAME.SelfHost.Shared/SelfHostResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NAME.SelfHost.Shared 6 | { 7 | /// 8 | /// Represents an IDisposable proxy object for the result of the SelfHost servers start. 9 | /// Contains the parsed dependencies. 10 | /// 11 | /// 12 | /// Disposing this object ensures that the underlying SelfHost server is stopped. 13 | /// 14 | public class SelfHostResult : IDisposable 15 | { 16 | /// 17 | /// Gets the parsed dependencies. 18 | /// 19 | /// 20 | /// The parsed dependencies. 21 | /// 22 | public ParsedDependencies ParsedDependencies { get; } 23 | 24 | /// 25 | /// Gets the port of the self hosted server. 26 | /// 27 | /// 28 | /// The port of the self hosted server. 29 | /// 30 | public int ServerPort 31 | { 32 | get 33 | { 34 | return this.selfHostServer.Port ?? 0; 35 | } 36 | } 37 | 38 | private ISelfHostServer selfHostServer; 39 | 40 | internal SelfHostResult(ParsedDependencies parsedDependencies, ISelfHostServer selfHostServer) 41 | { 42 | this.ParsedDependencies = parsedDependencies; 43 | this.selfHostServer = selfHostServer; 44 | } 45 | 46 | internal SelfHostResult(ParsedDependencies parsedDependencies) 47 | { 48 | this.ParsedDependencies = parsedDependencies; 49 | this.selfHostServer = null; 50 | } 51 | 52 | /// 53 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 54 | /// 55 | public void Dispose() 56 | { 57 | this.selfHostServer?.Dispose(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/NAME/ConnectionStrings/EnvironmentVariableConnectionStringProvider.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace NAME.ConnectionStrings 7 | { 8 | /// 9 | /// Represents a connection string value reader from a environment variable 10 | /// 11 | public class EnvironmentVariableConnectionStringProvider : IConnectionStringProvider 12 | { 13 | private string environmentVariable; 14 | 15 | /// 16 | /// creates a new instance of 17 | /// 18 | /// environment variable to searchfor 19 | public EnvironmentVariableConnectionStringProvider(string environmentVariable) 20 | { 21 | this.environmentVariable = environmentVariable; 22 | } 23 | 24 | /// 25 | /// gets the connection string 26 | /// 27 | /// connection string to return 28 | /// 29 | /// Returns true if the connection string was fetched successfully. 30 | /// 31 | public virtual bool TryGetConnectionString(out string connectionString) 32 | { 33 | connectionString = Environment.GetEnvironmentVariable(this.environmentVariable); 34 | 35 | return !string.IsNullOrWhiteSpace(connectionString); 36 | } 37 | 38 | /// 39 | /// Returns a that represents this instance. 40 | /// 41 | /// 42 | /// A that represents this instance. 43 | /// 44 | public override string ToString() 45 | { 46 | return $"Locator: {SupportedConnectionStringLocators.EnvironmentVariable}, EnvironmentVariable: {this.environmentVariable}"; 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.HttpListener/NAMEServer.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using NAME.Core.Exceptions; 3 | using NAME.Dependencies; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using SocketHttpListener.Net; 9 | using System.Text; 10 | using NAME.Hosting.Shared; 11 | using NAME.SelfHost.Shared; 12 | using static NAME.Hosting.Shared.DependenciesUtils; 13 | using static NAME.Utils.LogUtils; 14 | 15 | namespace NAME.SelfHost.HttpListener 16 | { 17 | /// 18 | /// Provides a mechanism to start a self hosted HTTP server serving the NAME endpoints using an HttpListener server. 19 | /// 20 | public static class NAMEServer 21 | { 22 | /// 23 | /// Enables the NAME self host server. 24 | /// 25 | /// The name configuration builder. 26 | /// 27 | /// Returns an proxy object containing the Parsed Dependencies and a way to stop the server. 28 | /// 29 | /// Error parsing the dependencies file. 30 | /// Happens when is set to true and dependencies check fail. 31 | public static SelfHostResult EnableName(Action nameConfigBuilder) 32 | { 33 | var nameConfiguration = new NAMEHttpListenerConfiguration(); 34 | nameConfigBuilder?.Invoke(nameConfiguration); 35 | 36 | var pathMapper = new StaticFilePathMapper(); 37 | 38 | var server = new HttpListenerServer(nameConfiguration, pathMapper); 39 | var parsedDependencies = SelfHostInitializer.Initialize(server, pathMapper, nameConfiguration); 40 | 41 | return new SelfHostResult(parsedDependencies, server); 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/NAME.SelfHost.Kestrel/KestrelServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using NAME.Core; 5 | using NAME.SelfHost.Shared; 6 | 7 | namespace NAME.SelfHost.Kestrel 8 | { 9 | internal class KestrelServer : ISelfHostServer 10 | { 11 | private IWebHost webHost; 12 | private NAMEKestrelConfiguration nameConfiguration; 13 | private IFilePathMapper pathMapper; 14 | 15 | public int? Port { get; private set; } 16 | 17 | public KestrelServer(NAMEKestrelConfiguration nameConfiguration, IFilePathMapper pathMapper) 18 | { 19 | this.pathMapper = pathMapper; 20 | this.nameConfiguration = nameConfiguration; 21 | } 22 | 23 | public bool Start(int port, NAMESettings settings) 24 | { 25 | try 26 | { 27 | this.webHost = new WebHostBuilder() 28 | .UseKestrel() 29 | .UseStartup() 30 | .UseUrls($"http://{this.nameConfiguration.AddressToListenOn}:{port}/{this.nameConfiguration.ManifestUriPrefix.TrimStart('/').TrimEnd('/')}/") 31 | .ConfigureServices((services) => 32 | { 33 | services.AddSingleton(settings); 34 | services.AddSingleton(this.nameConfiguration); 35 | services.AddSingleton(this.pathMapper); 36 | }) 37 | .Build(); 38 | 39 | this.webHost.Start(); 40 | 41 | this.Port = port; 42 | 43 | return true; 44 | } 45 | catch (Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException) 46 | { 47 | this.webHost?.Dispose(); 48 | return false; 49 | } 50 | } 51 | 52 | 53 | public void Dispose() 54 | { 55 | this.webHost?.Dispose(); 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/NAME.Core/Exceptions/VersionNotRecognizedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.Core.Exceptions 7 | { 8 | /// 9 | /// Represents an exception that happens when the provided version is not recognized. 10 | /// 11 | /// 12 | public class VersionNotRecognizedException : NAMEException 13 | { 14 | /// 15 | /// Gets or sets the version. 16 | /// 17 | /// 18 | /// The version. 19 | /// 20 | public string DependencyVersion { get; set; } 21 | 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | /// The version. 26 | public VersionNotRecognizedException(string version) 27 | : this(version, $"The version {version} was not recognized.") 28 | { 29 | 30 | } 31 | 32 | /// 33 | /// Initializes a new instance of the class. 34 | /// 35 | /// The version. 36 | /// The message. 37 | public VersionNotRecognizedException(string version, string message) 38 | : this(version, message, null) 39 | { 40 | } 41 | 42 | /// 43 | /// Initializes a new instance of the class. 44 | /// 45 | /// The version. 46 | /// The message. 47 | /// The inner exception. 48 | public VersionNotRecognizedException(string version, string message, Exception inner) 49 | : base(message, inner, NAMEStatusLevel.Warn) 50 | { 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /integration-tests/NAME.DummyService/NAME.DummyService.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp1.1 5 | true 6 | NAME.DummyService 7 | Exe 8 | NAME.DummyService 9 | 1.1.1 10 | $(PackageTargetFallback);dotnet5.6;portable-net45+win8 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/Service/ServiceVersionResolverTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.ConnectionStrings; 2 | using NAME.Core; 3 | using NAME.Core.Exceptions; 4 | using NAME.Service; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using Xunit; 10 | 11 | namespace NAME.Tests.Service 12 | { 13 | public class ServiceVersionResolverTests 14 | { 15 | [Fact] 16 | [Trait("TestCategory", "Unit")] 17 | public async Task GetVersions_NoEndpointListening() 18 | { 19 | string connectionString = "http://gibberish/nPVR"; 20 | IVersionResolver resolver = new ServiceVersionResolver(new StaticConnectionStringProvider(connectionString), 0, 5, 10000, 10000); 21 | 22 | await Assert.ThrowsAsync(typeof(DependencyNotReachableException), async () => 23 | { 24 | await resolver.GetVersions().ConfigureAwait(false); 25 | }); 26 | } 27 | 28 | [Fact] 29 | [Trait("TestCategory", "Unit")] 30 | public async Task GetVersions_NotFoundListening() 31 | { 32 | string connectionString = "http://localhost:65534/NonExistentService"; 33 | IVersionResolver resolver = new ServiceVersionResolver(new StaticConnectionStringProvider(connectionString), 0, 5, 10000, 10000); 34 | 35 | await Assert.ThrowsAsync(typeof(DependencyNotReachableException), async () => 36 | { 37 | await resolver.GetVersions().ConfigureAwait(false); 38 | }); 39 | } 40 | 41 | [Fact] 42 | [Trait("TestCategory", "Unit")] 43 | public async Task GetVersions_ConnectionStringNotFound() 44 | { 45 | IVersionResolver resolver = new ServiceVersionResolver(new DummyNotFoundConnectionStringProvider(), 0, 5, 10000, 10000); 46 | 47 | await Assert.ThrowsAsync(async () => 48 | { 49 | var value = await resolver.GetVersions().ConfigureAwait(false); 50 | }); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/NAME/ConnectionStrings/ConnectionStringsConnectionStringProvider.cs: -------------------------------------------------------------------------------- 1 | #if NET45 2 | using NAME.Core; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Configuration; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace NAME.ConnectionStrings 10 | { 11 | /// 12 | /// Provides a mechanism to fetch a connection string from the ConnectionStrings section. 13 | /// 14 | /// 15 | public class ConnectionStringsConnectionStringProvider : IConnectionStringProvider 16 | { 17 | 18 | private string key; 19 | 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | /// The key of the connection string. 24 | public ConnectionStringsConnectionStringProvider(string key) 25 | { 26 | this.key = key; 27 | } 28 | 29 | /// 30 | /// Gets the connection string. 31 | /// 32 | /// A containing the connection string. 33 | /// 34 | /// Returns true if the connection string was fetched successfully. 35 | /// 36 | public bool TryGetConnectionString(out string connectionString) 37 | { 38 | connectionString = ConfigurationManager.ConnectionStrings[this.key]?.ConnectionString; 39 | return connectionString != null; 40 | } 41 | 42 | /// 43 | /// Returns a that represents this instance. 44 | /// 45 | /// 46 | /// A that represents this instance. 47 | /// 48 | public override string ToString() 49 | { 50 | return $"Locator: {SupportedConnectionStringLocators.ConnectionStrings}, Key: {this.key}"; 51 | } 52 | } 53 | } 54 | #endif -------------------------------------------------------------------------------- /src/NAME.WebApi/Nuget/Content/App_Start/NAMEConfig.cs.pp: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Web.Http; 3 | using $rootnamespace$; 4 | using WebActivatorEx; 5 | using NAME; 6 | using NAME.WebApi; 7 | 8 | [assembly: PreApplicationStartMethod(typeof(NAMEConfig), "Register")] 9 | 10 | namespace $rootnamespace$ 11 | { 12 | 13 | /// 14 | /// Provides configuration for NAME. 15 | /// 16 | public class NAMEConfig 17 | { 18 | /// 19 | /// Registers the NAME plugin 20 | /// 21 | public static void Register() 22 | { 23 | //Enables NAME and checks that all the declared dependencies match the dependencies.json file. 24 | var assembly = typeof(NAMEConfig).Assembly; 25 | GlobalConfiguration.Configuration 26 | .EnableNAME(config => 27 | { 28 | // Use this property to tset the dependencies file. 29 | // By default it has the ~/dependencies.json value. 30 | // 31 | //config.DependenciesFilePath = "~/dependencies.json"; 32 | 33 | // Use this property to set the name provided in the Manifest. 34 | // 35 | config.APIName = assembly.GetName().Name; 36 | 37 | // Use this property to set the version provided in the Manifest 38 | // 39 | config.APIVersion = assembly.GetName().Version.ToString(); 40 | 41 | // Use this property to set a prefix for the URI (before the /manifest), by default the prefix is empty. 42 | // 43 | //config.ManifestUriPrefix = "api/"; 44 | 45 | // Uncomment the following line to interrupt the Web Api startup if any of the dependencies fail. 46 | // Warning: This will execute on Application recycle which may cause unexpected behaviours. 47 | // 48 | //config.ThrowOnDependenciesFail = true; 49 | }); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/NAME.Core/Json/IJsonNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NAME.Json 6 | { 7 | /// 8 | /// Provides a mechanism to acess json elements. 9 | /// 10 | public interface IJsonNode 11 | { 12 | /// 13 | /// Gets a child json element using the index. 14 | /// 15 | /// The index. 16 | IJsonNode this[int aIndex] 17 | { 18 | get; 19 | } 20 | 21 | /// 22 | /// Gets a child json element using the key. 23 | /// 24 | /// The key. 25 | IJsonNode this[string aKey] 26 | { 27 | get; 28 | } 29 | 30 | /// 31 | /// Gets the element value as string. 32 | /// 33 | string Value 34 | { 35 | get; 36 | } 37 | 38 | /// 39 | /// Gets the element value as int. 40 | /// 41 | int AsInt 42 | { 43 | get; 44 | } 45 | 46 | /// 47 | /// Gets the element value as long. 48 | /// 49 | long AsLong 50 | { 51 | get; 52 | } 53 | 54 | /// 55 | /// Gets the element value as float. 56 | /// 57 | float AsFloat 58 | { 59 | get; 60 | } 61 | 62 | /// 63 | /// Gets the element value as double. 64 | /// 65 | double AsDouble 66 | { 67 | get; 68 | } 69 | 70 | #pragma warning disable SA1623 // Property summary documentation must match accessors 71 | /// 72 | /// Gets the element value as bool. 73 | /// 74 | bool AsBool 75 | #pragma warning restore SA1623 // Property summary documentation must match accessors 76 | { 77 | get; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/NAME/OperatingSystem/WindowsVersions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.OperatingSystem 7 | { 8 | /// 9 | /// The possible Windows versions. 10 | /// 11 | public enum WindowsVersions 12 | { 13 | /// 14 | /// The Windows xp 15 | /// 16 | WindowsXP, 17 | 18 | /// 19 | /// The Windows xp professional x64 20 | /// 21 | WindowsXPProfessionalx64, 22 | 23 | /// 24 | /// The Windows Server 2003 25 | /// 26 | WindowsServer2003, 27 | 28 | /// 29 | /// The Windows Server 2003 R2 30 | /// 31 | WindowsServer2003R2, 32 | 33 | /// 34 | /// The Windows vista 35 | /// 36 | WindowsVista, 37 | 38 | /// 39 | /// The Windows Server 2008 40 | /// 41 | WindowsServer2008, 42 | 43 | /// 44 | /// The Windows Server 2008 R2 45 | /// 46 | WindowsServer2008R2, 47 | 48 | /// 49 | /// The Windows 7 50 | /// 51 | Windows7, 52 | 53 | /// 54 | /// The Windows Server 2012 55 | /// 56 | WindowsServer2012, 57 | 58 | /// 59 | /// The Windows 8 60 | /// 61 | Windows8, 62 | 63 | /// 64 | /// The Windows Server 2012 R2 65 | /// 66 | WindowsServer2012R2, 67 | 68 | /// 69 | /// The Windows 8.1 70 | /// 71 | Windows81, 72 | 73 | /// 74 | /// The Windows Server 2016 75 | /// 76 | WindowsServer2016, 77 | 78 | /// 79 | /// The Windows 10 80 | /// 81 | Windows10, 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/NAME.Core/Utils/SocketHelpers.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core.Exceptions; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net.Sockets; 6 | using System.Threading.Tasks; 7 | 8 | namespace NAME.Core.Utils 9 | { 10 | /// 11 | /// Provides helper methods for Sockets. 12 | /// 13 | internal static class SocketHelpers 14 | { 15 | /// 16 | /// Initializes a and connects to the specified host/port combination. 17 | /// 18 | /// The host. 19 | /// The port. 20 | /// Name of the dependency. 21 | /// The connect timeout. 22 | /// The read write timeout. 23 | /// 24 | /// Returns the initialized and connected . 25 | /// 26 | /// Happens when the connection to the host is not successfull. 27 | public static async Task OpenTcpClient(string host, int port, string dependencyName, int connectTimeout, int readWriteTimeout) 28 | { 29 | TcpClient client = null; 30 | try 31 | { 32 | client = new TcpClient(); 33 | 34 | client.NoDelay = true; 35 | client.ReceiveTimeout = connectTimeout; 36 | client.ReceiveTimeout = readWriteTimeout; 37 | client.SendTimeout = readWriteTimeout; 38 | await client.ConnectAsync(host, port).ConfigureAwait(false); 39 | 40 | return client; 41 | } 42 | catch (SocketException ex) 43 | { 44 | #if NET45 45 | if (client.Connected) 46 | client?.GetStream()?.Close(); 47 | client?.Close(); 48 | #else 49 | client?.Dispose(); 50 | #endif 51 | throw new DependencyNotReachableException(dependencyName, ex); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/ManifestGeneratorTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using System; 3 | using System.IO; 4 | using System.Reflection; 5 | using System.Threading.Tasks; 6 | using Xunit; 7 | using Newtonsoft.Json; 8 | using Newtonsoft.Json.Linq; 9 | 10 | namespace NAME.Tests 11 | { 12 | public class ManifestGeneratorTests 13 | { 14 | public static string CONFIGURATION_CONTENTS = @"{ 15 | ""$schema"": ""./config-manifest.schema.json"", 16 | ""infrastructure_dependencies"": [ 17 | ], 18 | ""service_dependencies"": [ 19 | ] 20 | }"; 21 | 22 | 23 | [Fact] 24 | [Trait("TestCategory", "Unit")] 25 | public async Task GenerateJson() 26 | { 27 | string fileName = Guid.NewGuid().ToString() + ".json"; 28 | try 29 | { 30 | File.WriteAllText(fileName, CONFIGURATION_CONTENTS); 31 | string expectedManifest = @"{ 32 | ""nameVersion"": """ + Constants.NAME_ASSEMBLY_VERSION + @""", 33 | ""name"":""NAME.Tests"", 34 | ""version"":""1.0.0"", 35 | ""infrastructure_dependencies"":[ 36 | ], 37 | ""service_dependencies"":[ 38 | ] 39 | }"; 40 | string appName = "NAME.Tests"; 41 | string appVersion = "123.1.2"; 42 | 43 | ParsedDependencies dependencies = DependenciesReader.ReadDependencies(fileName, new DummyFilePathMapper(), new NAMESettings(), new NAMEContext()); 44 | string manifest = await ManifestGenerator.GenerateJson(appName, appVersion, dependencies); 45 | 46 | var manifestObject = (JObject)JsonConvert.DeserializeObject(manifest); 47 | 48 | Assert.Equal(Constants.NAME_ASSEMBLY_VERSION, manifestObject["nameVersion"]); 49 | Assert.Equal(appName, manifestObject["name"]); 50 | Assert.Equal(appVersion, manifestObject["version"]); 51 | } 52 | finally 53 | { 54 | File.Delete(fileName); 55 | } 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/NAME.Core/Exceptions/DependencyNotReachableException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NAME.Core.Exceptions 7 | { 8 | /// 9 | /// Happens when dependency is not reachable by NAME. 10 | /// 11 | /// 12 | public class DependencyNotReachableException : NAMEException 13 | { 14 | /// 15 | /// Gets the name of the dependency. 16 | /// 17 | /// 18 | /// The name of the dependency. 19 | /// 20 | public string DependencyName { get; private set; } 21 | 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | /// Name of the dependency. 26 | /// The message that represents the error. 27 | /// Inner exception. 28 | public DependencyNotReachableException(string dependencyName, string message, Exception inner) 29 | : base(message, inner, NAMEStatusLevel.Error) 30 | { 31 | this.DependencyName = dependencyName; 32 | } 33 | 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | /// Name of the dependency. 38 | public DependencyNotReachableException(string dependencyName) 39 | : this(dependencyName, null) 40 | { 41 | } 42 | 43 | /// 44 | /// Initializes a new instance of the class. 45 | /// 46 | /// Name of the dependency. 47 | /// Inner exception. 48 | public DependencyNotReachableException(string dependencyName, Exception inner) 49 | : this(dependencyName, $"Dependency {dependencyName} is not reachable!", inner) 50 | { 51 | 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/NAME.Core/Json/SimpleJSONPathValueSystem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NAME.Json 8 | { 9 | internal class SimpleJsonPathValueSystem : IJsonPathValueSystem 10 | { 11 | 12 | public bool HasMember(object value, string member) 13 | { 14 | if (value is JsonClass) 15 | return (value as JsonClass)[member] != null; 16 | if (value is JsonArray) 17 | { 18 | int index = this.ParseInt(member, -1); 19 | return index >= 0 && index < (value as JsonArray).Count; 20 | } 21 | 22 | return false; 23 | } 24 | 25 | public IEnumerable GetMembers(object value) 26 | { 27 | var valueObject = value as JsonClass; 28 | if (valueObject != null) 29 | { 30 | foreach (KeyValuePair item in valueObject) 31 | { 32 | yield return item.Key; 33 | } 34 | } 35 | } 36 | 37 | public object GetMemberValue(object value, string member) 38 | { 39 | if (value is JsonClass) 40 | return (value as JsonClass)[member]; 41 | 42 | if (value is JsonArray) 43 | { 44 | int index = this.ParseInt(member, -1); 45 | return (value as JsonArray)[index]; 46 | } 47 | 48 | return null; 49 | } 50 | 51 | public bool IsArray(object value) 52 | { 53 | return value is JsonArray; 54 | } 55 | 56 | public bool IsObject(object value) 57 | { 58 | return value is JsonClass; 59 | } 60 | 61 | public bool IsPrimitive(object value) 62 | { 63 | if (value == null) 64 | throw new ArgumentNullException("value"); 65 | 66 | return value is JsonClass || value is JsonArray ? false : true; 67 | } 68 | 69 | private int ParseInt(string s, int defaultValue) 70 | { 71 | int result; 72 | return int.TryParse(s, out result) ? result : defaultValue; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/SqlServer/SqlServerVersionTranslatorTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using NAME.Core.Utils; 3 | using NAME.SqlServer; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using Xunit; 9 | using Xunit.Extensions; 10 | 11 | namespace NAME.Tests.SqlServer 12 | { 13 | public class SqlServerVersionTranslatorTests 14 | { 15 | [Theory] 16 | [Trait("TestCategory", "Unit")] 17 | [MemberData(nameof(TestData))] 18 | public void Translate_SqlServerVersions(SqlServerVersions version, string expectedVersion) 19 | { 20 | IVersionTranslator translator = new SqlServerVersionTranslator(); 21 | 22 | DependencyVersion v = translator.Translate(version.ToString()); 23 | 24 | Assert.True(v >= DependencyVersionParser.Parse(expectedVersion, false)); 25 | } 26 | 27 | [Theory] 28 | [Trait("TestCategory", "Unit")] 29 | [MemberData(nameof(TestData))] 30 | public void Translate_Versions(SqlServerVersions exptectedVersion, string versionStr) 31 | { 32 | IVersionTranslator translator = new SqlServerVersionTranslator(); 33 | 34 | string v = translator.Translate(DependencyVersionParser.Parse(versionStr, false)); 35 | 36 | Assert.True(v == exptectedVersion.ToString()); 37 | } 38 | 39 | public static IEnumerable TestData 40 | { 41 | get 42 | { 43 | return new[] 44 | { 45 | new object[] { SqlServerVersions.SqlServer2016, "13.0.2186" }, 46 | new object[] { SqlServerVersions.SqlServer2014,"12.0.2000" }, 47 | new object[] { SqlServerVersions.SqlServer2012, "11.0.2100" }, 48 | new object[] { SqlServerVersions.SqlServer2008R2, "10.50.1600" }, 49 | new object[] { SqlServerVersions.SqlServer2008, "10.0.1600" }, 50 | new object[] { SqlServerVersions.SqlServer2005, "9.0.1399" }, 51 | new object[] { SqlServerVersions.SqlServer2000, "8.0.384" }, 52 | new object[] { SqlServerVersions.SqlServer7, "7.0.623" } 53 | }; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /unit-tests/NAME.AspNetCore.Tests/NAME.AspNetCore.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp1.0;net452 5 | portable 6 | NAME.AspNetCore.Tests 7 | NAME.AspNetCore.Tests 8 | true 9 | $(PackageTargetFallback);dotnet5.4;portable-net451+win8 10 | 1.1.1 11 | false 12 | false 13 | false 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/NAME.Core/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Threading.Tasks; 6 | 7 | namespace NAME.Core 8 | { 9 | /// 10 | /// Provides constants for NAME. 11 | /// 12 | public static class Constants 13 | { 14 | /// 15 | /// Status code for when the maximum number of hops for a service resolver is reached. 16 | /// Changing this value WILL break backwards compatibility 17 | /// 18 | public const int SERVICE_HOPS_ERROR_STATUS_CODE = 508; 19 | 20 | /// 21 | /// The hop count header name 22 | /// Changing this value WILL break backwards compatibility 23 | /// 24 | public const string HOP_COUNT_HEADER_NAME = "X-NAME-Hop-Count"; 25 | 26 | /// 27 | /// The manifest endpoint header name. 28 | /// Changing this value WILL break backwards compatibility 29 | /// 30 | public const string MANIFEST_ENDPOINT_HEADER_NAME = "X-NAME-Manifest-Endpoint"; 31 | 32 | /// 33 | /// The manifest endpoint path. 34 | /// Changing this value WILL break backwards compatibility 35 | /// 36 | public const string MANIFEST_ENDPOINT = "/manifest"; 37 | 38 | /// 39 | /// The manifest UI endpoint path. 40 | /// Changing this value WILL break backwards compatibility 41 | /// 42 | public const string MANIFEST_UI_ENDPOINT = "/manifest/ui"; 43 | 44 | /// 45 | /// Gets the assembly version of NAME. 46 | /// 47 | /// 48 | /// The assembly version of NAME. 49 | /// 50 | public static string NAME_ASSEMBLY_VERSION => typeof(Constants).GetTypeInfo().Assembly.GetName().Version.ToString(3); 51 | 52 | /// 53 | /// Gets the NAME Registry supported protocol versions. 54 | /// 55 | /// 56 | /// The registry supported protocol versions. 57 | /// 58 | public static uint[] REGISTRY_SUPPORTED_PROTOCOL_VERSIONS 59 | { 60 | get 61 | { 62 | return new[] { 1u }; 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | First of all, thank you for considering contributing to NAME, we love contributions! 3 | 4 | ## Prerequisites 5 | By contributing, you assert that: 6 | * The contribution is your own original work. 7 | * You have the right to assign the copyright for the work (it is not owned by your employer, or you have been given copyright assignment in writing). 8 | 9 | ## Code 10 | ### Code Style 11 | We use the [normal .NET coding guidelines](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/) as a base for the coding style, with some changes such as: 12 | * Use 4 spaces for indentation (no tabs) 13 | * Use `camelCase` for private fiels (do not use `_` ) 14 | * Use `this.` when accessing instance members 15 | * Always specify member visibility, even if it's the default (i.e. `private string foo;` not `string foo;`) 16 | * All public members must be documented 17 | 18 | A StyleCop ruleset is included with the project, and the analyser is run for every build. Any StyleCop violation is considered as a Warning. Pull requests with incorrect styling will be rejected. 19 | 20 | ### Dependencies 21 | The assembly `NAME` should only have Microsoft's `System.*` dependencies, with the exception of `Microsoft.CSharp` that is required for the .Net 4.5 assembly. 22 | 23 | _Do not_ include the `NETStandard.Library` package in any project, you should always include the most specific package you need. 24 | 25 | ### Unit Tests 26 | Make sure to run all unit tests before creating a pull request. Any new code, including bugfixes, should have unit tests. 27 | 28 | To build and run the unit tests, run the build bootstrapper. 29 | 30 | On Windows: 31 | 32 | powershell ./build.ps1 33 | 34 | On Linux: 35 | 36 | ./build.sh 37 | 38 | Please note that the full unit tests suite will only run on Windows. 39 | 40 | ## Contributing Process 41 | Fork, then clone the repo: 42 | 43 | git clone git@github.com:your-username/name-sdk.git 44 | 45 | [Make sure the tests pass.](#unit-tests) 46 | 47 | Make your changes, including tests for the changes you made. 48 | 49 | Make sure the solution builds without warnings and tests pass again. 50 | 51 | Push to your fork and [submit a pull request](https://github.com/nosinovacao/name-sdk/compare/ 52 | ). 53 | 54 | Some things that will increase the chance that your pull request is accepted: 55 | 56 | * Write tests. 57 | * Follow our [code style](#code-style). 58 | * Write a good commit message. 59 | -------------------------------------------------------------------------------- /integration-tests/NAME.IntegrationTests/Service/SelfHostKestrelServiceVersionResolverTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.ConnectionStrings; 2 | using NAME.Core; 3 | using NAME.Core.Exceptions; 4 | using NAME.Core.Utils; 5 | using NAME.Service; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using Xunit; 9 | 10 | namespace NAME.IntegrationTests.Service 11 | { 12 | public class SelfHostKestrelServiceVersionResolverTests 13 | { 14 | [Fact] 15 | [Trait("TestCategory", "Integration")] 16 | public async Task GetVersions() 17 | { 18 | string connectionString = $"http://{ Constants.SpecificKestrelSelfHostHostname }:40500"; 19 | IVersionResolver resolver = new ServiceVersionResolver(new StaticConnectionStringProvider(connectionString), 0, 5, 10000, 10000); 20 | 21 | var versions = await resolver.GetVersions().ConfigureAwait(false); 22 | 23 | Assert.Equal(1, versions.Count()); 24 | Assert.Equal(versions.First(), DependencyVersionParser.Parse(Constants.SpecificKestrelSelfHostVersion, false)); 25 | } 26 | 27 | [Fact] 28 | [Trait("TestCategory", "Integration")] 29 | public async Task GetVersions_WrongEndpoint() 30 | { 31 | string connectionString = $"http://{ Constants.SpecificKestrelSelfHostHostname }:40500/api/v1"; 32 | IVersionResolver resolver = new ServiceVersionResolver(new StaticConnectionStringProvider(connectionString), 0, 5, 10000, 10000); 33 | 34 | var versions = await resolver.GetVersions().ConfigureAwait(false); 35 | 36 | Assert.Equal(1, versions.Count()); 37 | Assert.Equal(versions.First(), DependencyVersionParser.Parse(Constants.SpecificKestrelSelfHostVersion, false)); 38 | } 39 | 40 | [Fact] 41 | [Trait("TestCategory", "Integration")] 42 | public async Task GetVersions_WrongEndpoint_ReturnedOk() 43 | { 44 | string connectionString = $"http://{ Constants.SpecificKestrelSelfHostHostname }:40500/not/the/real"; 45 | IVersionResolver resolver = new ServiceVersionResolver(new StaticConnectionStringProvider(connectionString), 0, 5, 10000, 10000); 46 | 47 | var versions = await resolver.GetVersions().ConfigureAwait(false); 48 | 49 | Assert.Equal(1, versions.Count()); 50 | Assert.Equal(versions.First(), DependencyVersionParser.Parse(Constants.SpecificKestrelSelfHostVersion, false)); 51 | } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /stylecop.ruleset: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /unit-tests/NAME.AspNetCore.Tests/AspNetCoreConfigurationConnectionStringProviderTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Moq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using Xunit; 7 | 8 | namespace NAME.AspNetCore.Tests 9 | { 10 | public class AspNetCoreConfigurationConnectionStringProviderTests 11 | { 12 | [Fact] 13 | public void TryGetConnectionString_ReturnsTrue_WhenFound() 14 | { 15 | var key = "ConnectionStrings:Service"; 16 | var value = "http://example.com"; 17 | 18 | var configurationMock = new Mock(MockBehavior.Strict); 19 | configurationMock 20 | .SetupGet(c => c[key]) 21 | .Returns(value); 22 | 23 | var provider = new AspNetCoreConfigurationConnectionStringProvider(configurationMock.Object, key); 24 | var found = provider.TryGetConnectionString(out string connectionString); 25 | 26 | Assert.True(found); 27 | Assert.Equal(value, connectionString); 28 | } 29 | 30 | [Fact] 31 | public void TryGetConnectionString_ReturnsFalse_WhenNull() 32 | { 33 | var key = "ConnectionStrings:Service"; 34 | string value = null; 35 | 36 | var configurationMock = new Mock(MockBehavior.Strict); 37 | configurationMock 38 | .SetupGet(c => c[key]) 39 | .Returns(value); 40 | 41 | var provider = new AspNetCoreConfigurationConnectionStringProvider(configurationMock.Object, key); 42 | var found = provider.TryGetConnectionString(out string connectionString); 43 | 44 | Assert.False(found); 45 | Assert.Null(connectionString); 46 | } 47 | 48 | [Fact] 49 | public void TryGetConnectionString_ReturnsFalse_WhenException() 50 | { 51 | var key = "ConnectionStrings:Service"; 52 | 53 | var configurationMock = new Mock(MockBehavior.Strict); 54 | configurationMock 55 | .SetupGet(c => c[key]) 56 | .Throws(); 57 | 58 | var provider = new AspNetCoreConfigurationConnectionStringProvider(configurationMock.Object, key); 59 | var found = provider.TryGetConnectionString(out string connectionString); 60 | 61 | Assert.False(found); 62 | Assert.Null(connectionString); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 6 | 7 | ## v1.2.1 - 2019-07-04 8 | ### Fixed 9 | * Fix MongoDB version checker to use the command "buildInfo", which is more lightweight and without any timestamp type [#38] (https://github.com/nosinovacao/name-sdk/issues/38) 10 | 11 | ## v1.2.0 - 2018-08-09 12 | ### Added 13 | * Support for resolving the connection strings using environment variables [#16](https://github.com/nosinovacao/name-sdk/issues/16) 14 | * Extension point for the decision of which ConnectionString locator to use [#33](https://github.com/nosinovacao/name-sdk/issues/33) 15 | * Support for resolving the connection strings using the Asp.Net Core IConfiguration in the NAME.AspNetCore package [#33](https://github.com/nosinovacao/name-sdk/issues/33) 16 | 17 | ## v1.1.1 - 2018-02-22 18 | ### Fixed 19 | * Fix XPath connection string resolver incorrectly resolving the connection string when there were more XML elements after the provided XPath. 20 | 21 | ## v1.1.0 - 2017-11-09 22 | ### Fixed 23 | * Fix tab character '/t' breaking dependencies.json parsing. [(#10)](https://github.com/nosinovacao/name-sdk/issues/9) 24 | * Fix the table ui endpoint failing to load the manifest behind a HTTPS proxy. [(#9)](https://github.com/nosinovacao/name-sdk/issues/9) 25 | * Fix NAME not retrying to fetch a service dependency manifest from the correct endpoint when the dependency returned a successful status code. [(#8)](https://github.com/nosinovacao/name-sdk/issues/8) 26 | ### Added 27 | * A relevant error message is now shown when a service dependency does not have NAME installed. [(#14)](https://github.com/nosinovacao/name-sdk/issues/14) 28 | * Support for wildcards in the maximum version of dependencies. [(#11)](https://github.com/nosinovacao/name-sdk/issues/11) 29 | * Support for Elasticsearch version resolving. [(#19)](https://github.com/nosinovacao/name-sdk/issues/19) 30 | * A status field for each dependency in the manifest that describes its error level. [(#24)](https://github.com/nosinovacao/name-sdk/issues/24) 31 | * Startup healthcheck is now performed asynchronously when `ThrowOnDependenciesFail` is set to false. [(#4)](https://github.com/nosinovacao/name-sdk/issues/19) 32 | 33 | ## v1.0.0 - 2017-07-07 34 | * Initial open source release. 35 | 36 | 37 | [Unreleased]: https://github.com/nosinovacao/name-sdk/compare/v1.1.0...HEAD 38 | -------------------------------------------------------------------------------- /integration-tests/NAME.IntegrationTests/RabbitMq/RabbitMqVersionResolverTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using NAME.MongoDb; 3 | using NAME.RabbitMq; 4 | using NAME.ConnectionStrings; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using Xunit; 10 | using NAME.Core.Utils; 11 | 12 | namespace NAME.IntegrationTests.RabbitMq 13 | { 14 | public class RabbitMqVersionResolverTests 15 | { 16 | [Fact] 17 | [Trait("TestCategory", "Integration")] 18 | public async Task GetVersions_LatestVersion() 19 | { 20 | string connectionString = $"amqp://gibberish:notneeded@{ Constants.LatestRabbitHostname }:5672/"; 21 | IVersionResolver resolver = new RabbitMqVersionResolver(new StaticConnectionStringProvider(connectionString), 10000, 10000); 22 | 23 | var versions = await resolver.GetVersions().ConfigureAwait(false); 24 | 25 | Assert.Equal(1, versions.Count()); 26 | Assert.True(versions.First() >= DependencyVersionParser.Parse("3.6.5", false)); 27 | } 28 | 29 | [Fact] 30 | [Trait("TestCategory", "Integration")] 31 | public async Task GetVersions_SpecificVersion() 32 | { 33 | string connectionString = $"amqp://gibberish:notneeded@{ Constants.SpecificRabbitHostname }:5672/"; 34 | IVersionResolver resolver = new RabbitMqVersionResolver(new StaticConnectionStringProvider(connectionString), 10000, 10000); 35 | 36 | var versions = await resolver.GetVersions().ConfigureAwait(false); 37 | 38 | Assert.Equal(1, versions.Count()); 39 | Assert.Equal(versions.First(), DependencyVersionParser.Parse(Constants.SpecificRabbitVersion, false)); 40 | } 41 | 42 | [Fact] 43 | [Trait("TestCategory", "Integration")] 44 | public async Task GetVersions_MultipleConnectionStrings() 45 | { 46 | string connectionString = $"amqp://gibberish:notneeded@{ Constants.SpecificRabbitHostname }:5672/, amqp://gibberish:notneeded@{ Constants.LatestRabbitHostname }:5672/"; 47 | IVersionResolver resolver = new RabbitMqVersionResolver(new StaticConnectionStringProvider(connectionString), 10000, 10000); 48 | 49 | var versions = await resolver.GetVersions().ConfigureAwait(false); 50 | 51 | Assert.Equal(2, versions.Count()); 52 | Assert.Equal(versions.First(), DependencyVersionParser.Parse(Constants.SpecificRabbitVersion, false)); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/NAME/Dependencies/OperatingSystemDependency.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using NAME.Core; 6 | using NAME.Json; 7 | using NAME.OperatingSystem; 8 | using NAME.Core.Exceptions; 9 | 10 | namespace NAME.Dependencies 11 | { 12 | internal class OperatingSystemDependency : VersionedDependency 13 | { 14 | public OperatingSystemDependency() 15 | : base(new OperatingSystemVersionResolver()) 16 | { 17 | } 18 | 19 | public override async Task GetStatus() 20 | { 21 | try 22 | { 23 | IEnumerable actualVersions = await this.VersionResolver.GetVersions().ConfigureAwait(false); 24 | if (!actualVersions.Any()) 25 | return new DependencyCheckStatus(NAMEStatusLevel.Warn, message: "Could not fetch the actual versions."); 26 | 27 | foreach (var version in actualVersions) 28 | { 29 | var osVersion = version as OperatingSystemDependencyVersion; 30 | 31 | if (osVersion == null || !osVersion.OperatingSystem.Equals(this.OperatingSystemName, StringComparison.OrdinalIgnoreCase)) 32 | { 33 | return new DependencyCheckStatus(NAMEStatusLevel.Error, message: $"Unsupported Operating system { osVersion?.OperatingSystem }.)"); 34 | } 35 | 36 | if (version < this.MinimumVersion || (this.MaximumVersion != null && version > this.MaximumVersion)) 37 | { 38 | return new DependencyCheckStatus(NAMEStatusLevel.Error, version: version, message: $"Unsupported version.)"); 39 | } 40 | } 41 | 42 | return new DependencyCheckStatus(NAMEStatusLevel.Ok, actualVersions.FirstOrDefault()); 43 | } 44 | catch (NAMEException ex) 45 | { 46 | return new DependencyCheckStatus(ex.StatusLevel, message: ex.Message, innerException: ex.InnerException); 47 | } 48 | catch (Exception ex) 49 | { 50 | return new DependencyCheckStatus(NAMEStatusLevel.Error, message: ex.Message, innerException: ex.InnerException); 51 | } 52 | } 53 | 54 | public string OperatingSystemName { get; set; } 55 | 56 | public override string ToString() 57 | { 58 | return string.IsNullOrEmpty(this.Name) ? this.OperatingSystemName : this.Name; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/NAME/NAME.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Provides a way to expose service information (e.g. software version and all the service dependencies versions). 5 | netstandard1.6;net45 6 | true 7 | NAME 8 | NAME 9 | $(PackageTargetFallback);dnxcore50 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | . 19 | 20 | 21 | true 22 | content 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/NAME/ManifestGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using NAME.Json; 6 | using System.IO; 7 | using NAME.Core; 8 | 9 | namespace NAME 10 | { 11 | /// 12 | /// Provides mechanisms to generate a manifest. 13 | /// 14 | public static class ManifestGenerator 15 | { 16 | /// 17 | /// Generates a json representation of the manifest; 18 | /// 19 | /// The name. 20 | /// The version. 21 | /// The dependencies. 22 | /// Returns a task representing the asynchronous operation. The result contains the generated json manifest. 23 | public static async Task GenerateJson(string name, string version, ParsedDependencies dependencies) 24 | { 25 | JsonClass rootJson = new JsonClass(); 26 | rootJson.Add("nameVersion", Constants.NAME_ASSEMBLY_VERSION); 27 | rootJson.Add("name", name); 28 | 29 | if (version.Count(c => c == '.') > 2) 30 | version = string.Join(".", version.Split('.').Take(3)); 31 | 32 | rootJson.Add("version", version); 33 | 34 | List> infrastructureTasks = new List>(); 35 | foreach (var dependency in dependencies.InfrastructureDependencies) 36 | { 37 | infrastructureTasks.Add(dependency.ToJson()); 38 | } 39 | List> serviceTasks = new List>(); 40 | foreach (var dependency in dependencies.ServiceDependencies) 41 | { 42 | serviceTasks.Add(dependency.ToJson()); 43 | } 44 | await Task.WhenAll(Task.WhenAll(serviceTasks), Task.WhenAll(infrastructureTasks)).ConfigureAwait(false); 45 | 46 | JsonArray infrastructureDependencies = new JsonArray(); 47 | JsonArray serviceDependencies = new JsonArray(); 48 | foreach (var task in serviceTasks) 49 | { 50 | serviceDependencies.Add(task.Result); 51 | } 52 | foreach (var task in infrastructureTasks) 53 | { 54 | infrastructureDependencies.Add(task.Result); 55 | } 56 | rootJson.Add("infrastructure_dependencies", infrastructureDependencies); 57 | rootJson.Add("service_dependencies", serviceDependencies); 58 | 59 | return rootJson.ToString(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/NAME/Utils/LogUtils.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using NAME.Dependencies; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace NAME.Utils 9 | { 10 | /// 11 | /// Log-related util functions 12 | /// 13 | public static class LogUtils 14 | { 15 | /// 16 | /// Logs with information importance. 17 | /// 18 | /// The message. 19 | /// if set to true logs to console. 20 | public static void LogInfo(string message, bool logToConsole) 21 | { 22 | System.Diagnostics.Trace.TraceInformation(message); 23 | if (logToConsole) 24 | Console.WriteLine("[INFO] " + message); 25 | } 26 | 27 | /// 28 | /// Logs with warning importance. 29 | /// 30 | /// The message. 31 | /// if set to true logs to console. 32 | public static void LogWarning(string message, bool logToConsole) 33 | { 34 | System.Diagnostics.Trace.TraceWarning(message); 35 | if (logToConsole) 36 | Console.WriteLine("[WARN] " + message); 37 | } 38 | 39 | /// 40 | /// Logs the dependencies statuses. 41 | /// 42 | /// The dependencies. 43 | /// if set to true logs to console. 44 | /// A list with the status for all the dependencies. 45 | public static List LogDependenciesStatuses(IEnumerable dependencies, bool logToConsole) 46 | { 47 | List allStatuses = new List(); 48 | foreach (var dependency in dependencies) 49 | { 50 | var status = dependency.GetStatus().ConfigureAwait(false).GetAwaiter().GetResult(); 51 | string versionStr = status.Version != null ? $" ({status.Version})" : string.Empty; 52 | 53 | if (status.CheckStatus == NAMEStatusLevel.Ok) 54 | LogInfo($"{dependency}{versionStr} check passed.", logToConsole); 55 | else 56 | LogWarning($"{dependency}{versionStr} check {status.CheckStatus.ToString()} with message: {status.Message}.", logToConsole); 57 | 58 | allStatuses.Add(status); 59 | } 60 | return allStatuses; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /integration-tests/NAME.IntegrationTests/SqlServer/SqlServerVersionResolverTests.cs: -------------------------------------------------------------------------------- 1 | using NAME.Core; 2 | using NAME.Core.Exceptions; 3 | using NAME.MongoDb; 4 | using NAME.SqlServer; 5 | using NAME.ConnectionStrings; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | using Xunit; 11 | using NAME.Core.Utils; 12 | 13 | namespace NAME.IntegrationTests.SqlServer 14 | { 15 | public class SqlServerVersionResolverTests 16 | { 17 | [Fact] 18 | [Trait("TestCategory", "Integration")] 19 | public async Task GetVersions_SingleServer() 20 | { 21 | string connectionString = $"Data Source={ Constants.LatestSqlServerHostname };Initial Catalog=DBTests;Integrated Security=True;"; 22 | IVersionResolver resolver = new SqlServerVersionResolver(new StaticConnectionStringProvider(connectionString), 10000, 10000); 23 | 24 | var versions = await resolver.GetVersions().ConfigureAwait(false); 25 | 26 | Assert.Equal(1, versions.Count()); 27 | Assert.True(versions.First() >= DependencyVersionParser.Parse("12.0.0", false), "The version should be greater than 12.0.0"); 28 | } 29 | [Fact] 30 | [Trait("TestCategory", "Integration")] 31 | public async Task GetVersions_SpecificPort() 32 | { 33 | string connectionString = $"Data Source={ Constants.LatestSqlServerHostname },1433;Initial Catalog=DBTests;Integrated Security=True;"; 34 | IVersionResolver resolver = new SqlServerVersionResolver(new StaticConnectionStringProvider(connectionString), 10000, 10000); 35 | 36 | var versions = await resolver.GetVersions().ConfigureAwait(false); 37 | 38 | Assert.Equal(1, versions.Count()); 39 | Assert.True(versions.First() >= DependencyVersionParser.Parse("12.0.0", false), "The version should be greater than 12.0.0"); 40 | } 41 | [Fact] 42 | [Trait("TestCategory", "Integration")] 43 | public async Task GetVersions_EntityFrameworkConnectionString() 44 | { 45 | string connectionString = $"metadata = res://*/ProfilePreferences.csdl|res://*/ProfilePreferences.ssdl|res://*/ProfilePreferences.msl;provider=System.Data.SqlClient;provider connection string=\"Data Source={ Constants.LatestSqlServerHostname },1433;initial catalog=SomeDb;user id=user;password=pass;MultipleActiveResultSets=True;App=EntityFramework\""; 46 | IVersionResolver resolver = new SqlServerVersionResolver(new StaticConnectionStringProvider(connectionString), 10000, 10000); 47 | 48 | var versions = await resolver.GetVersions().ConfigureAwait(false); 49 | 50 | Assert.Equal(1, versions.Count()); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/Digest/Digest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace NAME.Tests.Digest 4 | { 5 | public class Digest 6 | { 7 | private const string genericMessage = "The quick brown fox jumps over the lazy dog"; 8 | private const string genericAvalancheMessage = "The quick brown fox jumps over the lazy dog."; 9 | 10 | [Fact] 11 | [Trait("TestCategory", "Unit")] 12 | public void TestEmptyMD5() 13 | { 14 | const string expectedDigest = "d41d8cd98f00b204e9800998ecf8427e"; 15 | TestValue(string.Empty, expectedDigest); 16 | } 17 | 18 | [Fact] 19 | [Trait("TestCategory", "Unit")] 20 | public void TestSpecificMD5() 21 | { 22 | const string expectedDigest = "9e107d9d372bb6826bd81d3542a419d6"; 23 | TestValue(genericMessage, expectedDigest); 24 | } 25 | 26 | [Fact] 27 | [Trait("TestCategory", "Unit")] 28 | public void TestAvalancheEffectMD5() 29 | { 30 | const string expectedDigest = "e4d909c290d0fb1ca068ffaddf22cbd0"; 31 | TestValue(genericAvalancheMessage, expectedDigest); 32 | } 33 | 34 | [Fact] 35 | [Trait("TestCategory", "Unit")] 36 | public void TestEmptySHA1() 37 | { 38 | const string algorithm = "SHA1"; 39 | const string expectedDigest = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; 40 | TestValue(algorithm, string.Empty, expectedDigest); 41 | } 42 | 43 | 44 | [Fact] 45 | [Trait("TestCategory", "Unit")] 46 | public void TestSpecificSHA1() 47 | { 48 | const string algorithm = "SHA1"; 49 | const string expectedDigest = "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"; 50 | TestValue(algorithm, genericMessage, expectedDigest); 51 | } 52 | 53 | [Fact] 54 | [Trait("TestCategory", "Unit")] 55 | public void TestAvalancheEffectSHA1() 56 | { 57 | const string algorithm = "SHA1"; 58 | const string expectedDigest = "408d94384216f890ff7a0c3528e8bed1e0b01621"; 59 | TestValue(algorithm, genericAvalancheMessage, expectedDigest); 60 | } 61 | 62 | private static void TestValue(string algorithm, string message, string expected) 63 | { 64 | var helperResult = DigestHelpers.DigestHelper.GetDigestForMessage(algorithm, message); 65 | Assert.Equal(expected, helperResult); 66 | } 67 | 68 | private static void TestValue(string message, string expected) 69 | { 70 | var helperResult = DigestHelpers.DigestHelper.GetDigestForMessage(message); 71 | Assert.Equal(expected, helperResult); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/OperatingSystem/WindowsVersionTranslatorTests.cs: -------------------------------------------------------------------------------- 1 | 2 | using NAME.Core; 3 | using NAME.Core.Exceptions; 4 | using NAME.Core.Utils; 5 | using NAME.OperatingSystem; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Runtime.InteropServices; 10 | using System.Threading.Tasks; 11 | using Xunit; 12 | 13 | namespace NAME.Tests.OperatingSystem 14 | { 15 | public class WindowsVersionTranslatorTests 16 | { 17 | 18 | [Theory] 19 | [Trait("TestCategory", "Unit")] 20 | [InlineData(WindowsVersions.WindowsXP, "5.1")] 21 | [InlineData(WindowsVersions.WindowsXPProfessionalx64, "5.2")] 22 | [InlineData(WindowsVersions.WindowsServer2003, "5.2")] 23 | [InlineData(WindowsVersions.WindowsServer2003R2, "5.2")] 24 | [InlineData(WindowsVersions.WindowsVista, "6.0")] 25 | [InlineData(WindowsVersions.WindowsServer2008, "6.0")] 26 | [InlineData(WindowsVersions.WindowsServer2008R2, "6.1")] 27 | [InlineData(WindowsVersions.Windows7, "6.1")] 28 | [InlineData(WindowsVersions.WindowsServer2012, "6.2")] 29 | [InlineData(WindowsVersions.Windows8, "6.2")] 30 | [InlineData(WindowsVersions.WindowsServer2012R2, "6.3")] 31 | [InlineData(WindowsVersions.Windows81, "6.3")] 32 | [InlineData(WindowsVersions.WindowsServer2016, "10.0")] 33 | [InlineData(WindowsVersions.Windows10, "10.0")] 34 | public void Translate_WindowsVersions(WindowsVersions version, string expectedVersion) 35 | { 36 | IVersionTranslator translator = new WindowsVersionTranslator(); 37 | 38 | DependencyVersion v = translator.Translate(version.ToString()); 39 | 40 | Assert.True(v >= DependencyVersionParser.Parse(expectedVersion, false)); 41 | } 42 | 43 | [Theory] 44 | [Trait("TestCategory", "Unit")] 45 | [InlineData(WindowsVersions.WindowsXP, "5.1")] 46 | [InlineData(WindowsVersions.WindowsServer2003, "5.2")] 47 | [InlineData(WindowsVersions.WindowsServer2008, "6.0")] 48 | [InlineData(WindowsVersions.WindowsServer2008R2, "6.1")] 49 | [InlineData(WindowsVersions.WindowsServer2012, "6.2")] 50 | [InlineData(WindowsVersions.WindowsServer2012R2, "6.3")] 51 | [InlineData(WindowsVersions.WindowsServer2016, "10.0")] 52 | public void Translate_Versions(WindowsVersions exptectedVersion, string versionStr) 53 | { 54 | IVersionTranslator translator = new WindowsVersionTranslator(); 55 | 56 | string v = translator.Translate(new OperatingSystemDependencyVersion("windows", DependencyVersionParser.Parse(versionStr, false))); 57 | 58 | Assert.True(v == exptectedVersion.ToString()); 59 | } 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /integration-tests/NAME.IntegrationTests/ManifestExplorer/ManifestExplorerTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using NAME.ConnectionStrings; 6 | using NAME.Core; 7 | using NAME.Dependencies; 8 | using NAME.Service; 9 | using Xunit; 10 | 11 | namespace NAME.IntegrationTests.ManifestExplorer 12 | { 13 | public class ManifestExplorerTests 14 | { 15 | [Fact, Trait("Category", "Integration")] 16 | public async Task TestExplorer() 17 | { 18 | const string manifest = @"{ 19 | ""infrastructure_dependencies"": [ ], 20 | ""service_dependencies"": [ 21 | { 22 | ""name"":""DummyConsoleKestrel"", 23 | ""min_version"": ""1.0.0"", 24 | ""max_version"": ""2.0.0"", 25 | ""connection_string"": ""http://dummy-console-kestrel:40500"" 26 | } 27 | ] 28 | }"; 29 | 30 | var memoryStream = new MemoryStream(); 31 | using (var streamWriter = new StreamWriter(memoryStream)) 32 | { 33 | await streamWriter.WriteAsync(manifest).ConfigureAwait(false); 34 | await streamWriter.FlushAsync().ConfigureAwait(false); 35 | memoryStream.Seek(0, SeekOrigin.Begin); 36 | 37 | ParsedDependencies parsedDependencies = DependenciesReader.ReadDependencies(memoryStream, new DummyFilePathMapper(), new Core.NAMESettings(), new Core.NAMEContext()); 38 | 39 | Assert.True(1 == parsedDependencies.ServiceDependencies.Count(), "The number of service dependencies did not match."); 40 | Assert.Empty(parsedDependencies.InfrastructureDependencies); 41 | 42 | var serviceDependency = parsedDependencies.ServiceDependencies.First(); 43 | 44 | DependencyCheckStatus status = await serviceDependency.GetStatus().ConfigureAwait(false); 45 | 46 | // we still need to test for backwards compatibility 47 | #pragma warning disable CS0618 // Type or member is obsolete 48 | Assert.True(status.CheckPassed); 49 | #pragma warning restore CS0618 // Type or member is obsolete 50 | Assert.Equal(NAMEStatusLevel.Ok, status.CheckStatus); 51 | Assert.NotNull(status.Version.ManifestNode); 52 | Assert.Equal("1.0.0", status.Version.ToString()); 53 | Assert.Equal("NAME.DummyService", status.Version.ManifestNode["name"]); 54 | Assert.Empty(status.Version.ManifestNode["infrastructure_dependencies"].Children); 55 | Assert.Empty(status.Version.ManifestNode["service_dependencies"].Children); 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /integration-tests/NAME.IntegrationTests/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | public static class Constants 4 | { 5 | public static string ExpectedOperatingSystem; 6 | 7 | // Latest versions 8 | public static string LatestMongoHostname; 9 | public static string LatestRabbitHostname; 10 | public static string LatestSqlServerHostname; 11 | 12 | // Specific versions 13 | public static string SpecificMongoHostname; 14 | public static string SpecificRabbitHostname; 15 | public static string SpecificServiceHostname; 16 | public static string SpecificKestrelSelfHostHostname; 17 | 18 | public static string SpecificMongoVersion; 19 | public static string SpecificRabbitVersion; 20 | public static string SpecificServiceVersion; 21 | public static string SpecificKestrelSelfHostVersion; 22 | 23 | // Elasticsearch variables 24 | public static string LatestElasticsearchHostname; 25 | public static string SpecificElasticsearchHostname; 26 | public static string SpecificElasticsearchVersion; 27 | 28 | static Constants() { 29 | ExpectedOperatingSystem = Environment.GetEnvironmentVariable("OPERATING_SYSTEM") ?? "windows"; 30 | 31 | LatestMongoHostname = Environment.GetEnvironmentVariable("LATEST_MONGO_HOSTNAME") ?? "localhost"; 32 | LatestRabbitHostname = Environment.GetEnvironmentVariable("LATEST_RABBIT_HOSTNAME") ?? "localhost"; 33 | LatestSqlServerHostname = Environment.GetEnvironmentVariable("LATEST_SQLSERVER_HOSTNAME") ?? "localhost"; 34 | 35 | SpecificMongoHostname = Environment.GetEnvironmentVariable("SPECIFIC_MONGO_HOSTNAME") ?? "localhost"; 36 | SpecificRabbitHostname = Environment.GetEnvironmentVariable("SPECIFIC_RABBIT_HOSTNAME") ?? "localhost"; 37 | SpecificServiceHostname = Environment.GetEnvironmentVariable("SPECIFIC_SERVICE_HOSTNAME") ?? "dummy-service"; 38 | SpecificKestrelSelfHostHostname = Environment.GetEnvironmentVariable("SPECIFIC_KESTREL_SELFHOST_HOSTNAME") ?? "localhost"; 39 | 40 | SpecificMongoVersion = Environment.GetEnvironmentVariable("SPECIFIC_MONGO_VERSION") ?? "3.0.0"; 41 | SpecificRabbitVersion = Environment.GetEnvironmentVariable("SPECIFIC_RABBIT_VERSION") ?? "3.6.5"; 42 | SpecificServiceVersion = Environment.GetEnvironmentVariable("SPECIFIC_SERVICE_VERSION") ?? "1.0.0"; 43 | SpecificKestrelSelfHostVersion = Environment.GetEnvironmentVariable("SPECIFIC_KESTREL_SELFHOST_VERSION") ?? "1.0.0"; 44 | 45 | LatestElasticsearchHostname = Environment.GetEnvironmentVariable("LATEST_ELASTICSEARCH_HOSTNAME") ?? "localhost"; 46 | SpecificElasticsearchHostname = Environment.GetEnvironmentVariable("SPECIFIC_ELASTICSEARCH_HOSTNAME") ?? "localhost"; 47 | SpecificElasticsearchVersion = Environment.GetEnvironmentVariable("SPECIFIC_ELASTICSEARCH_VERSION") ?? "5.5.1"; 48 | } 49 | } -------------------------------------------------------------------------------- /integration-tests/NAME.DummyService/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Logging; 10 | using NAME.AspNetCore; 11 | 12 | namespace NAME.DummyService 13 | { 14 | public class Startup 15 | { 16 | public Startup(IHostingEnvironment env) 17 | { 18 | var builder = new ConfigurationBuilder() 19 | .SetBasePath(env.ContentRootPath) 20 | .AddEnvironmentVariables() 21 | .AddJsonFile("appsettings.json"); 22 | Configuration = builder.Build(); 23 | } 24 | 25 | public IConfigurationRoot Configuration { get; } 26 | 27 | // This method gets called by the runtime. Use this method to add services to the container. 28 | public void ConfigureServices(IServiceCollection services) 29 | { 30 | // Add framework services. 31 | services.AddMvc(); 32 | } 33 | 34 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 35 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 36 | { 37 | loggerFactory.AddConsole(Configuration.GetSection("Logging")); 38 | loggerFactory.AddDebug(); 39 | 40 | app.Use(async (context, next) => 41 | { 42 | if (context.Request.Path.HasValue) 43 | { 44 | if (context.Request.Path.Value == "/endpoint/before/name/middleware/manifest") 45 | { 46 | context.Response.StatusCode = 200; 47 | return; 48 | } 49 | } 50 | await next(); 51 | }); 52 | 53 | app.UseNAME(config => 54 | { 55 | config.APIName = "Dummy"; 56 | config.APIVersion = "1.0.0"; 57 | config.DependenciesFilePath = "dependencies.json"; 58 | config.Configuration = Configuration; 59 | }); 60 | 61 | app.Use(async (context, next) => 62 | { 63 | if (context.Request.Path.HasValue) 64 | { 65 | if (context.Request.Path.Value == "/not/the/real/manifest") 66 | { 67 | context.Response.StatusCode = 200; 68 | return; 69 | } 70 | } 71 | await next(); 72 | }); 73 | 74 | app.UseMvc(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/NAME.Hosting.Shared/NAMEBaseConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace NAME.Hosting.Shared 5 | { 6 | /// 7 | /// Represents the base configuration used for NAME. 8 | /// 9 | public class NAMEBaseConfiguration 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | public NAMEBaseConfiguration() 15 | { 16 | this.ManifestUriPrefix = string.Empty; 17 | this.DependenciesFilePath = string.Empty; 18 | this.APIName = string.Empty; 19 | this.APIVersion = string.Empty; 20 | this.ThrowOnDependenciesFail = false; 21 | } 22 | 23 | /// 24 | /// Gets or sets the dependencies file path. 25 | /// 26 | /// 27 | /// The dependencies file path. 28 | /// 29 | public string DependenciesFilePath { get; set; } 30 | 31 | /// 32 | /// Gets or sets the name of the API. 33 | /// 34 | /// 35 | /// The name of the API. 36 | /// 37 | public string APIName { get; set; } 38 | 39 | private string apiVersion; 40 | 41 | /// 42 | /// Gets or sets the API version. 43 | /// 44 | /// 45 | /// The API version. 46 | /// 47 | public string APIVersion 48 | { 49 | get 50 | { 51 | return this.apiVersion; 52 | } 53 | set 54 | { 55 | int dotsCount = value.Length - value.Replace(".", string.Empty).Length; 56 | if (dotsCount > 2) 57 | this.apiVersion = value.Substring(0, value.LastIndexOf('.')); 58 | else 59 | this.apiVersion = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Gets or sets a value indicating whether an exception should be thrown when enabling NAME if any of the dependencies don't match the specified versions. 65 | /// If false, the dependencies state can be checked in the System.Diagnostics traces. 66 | /// 67 | /// 68 | /// true if an exception should be thrown; otherwise, false. 69 | /// 70 | public bool ThrowOnDependenciesFail { get; set; } 71 | 72 | /// 73 | /// Gets or sets the manifest prefix, to be used before /manifest. 74 | /// 75 | /// 76 | /// The manifest prefix, to be used before /manifest. 77 | /// 78 | public string ManifestUriPrefix { get; set; } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /unit-tests/NAME.Tests/ConnectionStrings/JsonPathConnectionStringProviderTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Xunit; 6 | using NAME.Core; 7 | using NAME.ConnectionStrings; 8 | using System.Reflection; 9 | using System.Xml; 10 | using System.IO; 11 | 12 | namespace NAME.Tests.ConnectionStrings 13 | { 14 | public class JsonPathConnectionStringProviderTests : IDisposable 15 | { 16 | private string CONFIGURATION_FILE = Guid.NewGuid() + ".json"; 17 | private const string CONFIGURATION_CONTENTS = 18 | @"{ 19 | ""ConnectionStrings"": { 20 | ""MongoConnection"": ""mongodb://some-mongo:27017/some-db"" 21 | } 22 | }"; 23 | 24 | public JsonPathConnectionStringProviderTests() 25 | { 26 | if (File.Exists(CONFIGURATION_FILE)) 27 | File.Delete(CONFIGURATION_FILE); 28 | File.WriteAllText(CONFIGURATION_FILE, CONFIGURATION_CONTENTS); 29 | } 30 | public void Dispose() 31 | { 32 | File.Delete(CONFIGURATION_FILE); 33 | } 34 | 35 | [Fact] 36 | [Trait("TestCategory", "Unit")] 37 | public void TryGetConnectionString() 38 | { 39 | IConnectionStringProvider provider = new JsonPathConnectionStringProvider(CONFIGURATION_FILE, "$.ConnectionStrings.MongoConnection"); 40 | bool result = provider.TryGetConnectionString(out string outConnection); 41 | 42 | Assert.True(result, "The connection string was not found!"); 43 | Assert.Equal("mongodb://some-mongo:27017/some-db", outConnection); 44 | } 45 | 46 | [Fact] 47 | [Trait("TestCategory", "Unit")] 48 | public void OnceUponALovelyDayWhenAttemptingToInvokeTryGetConnectionStringIWasExpectingTheKeyToNotBeFound() 49 | { 50 | IConnectionStringProvider provider = new JsonPathConnectionStringProvider(CONFIGURATION_FILE, "$.ConnectionStrings.MongoConnection" + "Thou shall not find the key!"); 51 | bool result = provider.TryGetConnectionString(out string outConnection); 52 | 53 | Assert.False(result, "The connection string should not be found."); 54 | Assert.Null(outConnection); 55 | } 56 | 57 | [Fact] 58 | [Trait("TestCategory", "Unit")] 59 | public void TryGetConnectionString_FileNotFound() 60 | { 61 | IConnectionStringProvider provider = new JsonPathConnectionStringProvider(CONFIGURATION_FILE + "Thou shall not find the file!", "$.ConnectionStrings.MongoConnection"); 62 | bool result = provider.TryGetConnectionString(out string outConnection); 63 | 64 | Assert.False(result, "The file should not be found."); 65 | Assert.Null(outConnection); 66 | } 67 | 68 | } 69 | } -------------------------------------------------------------------------------- /integration-tests/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | 3 | services: 4 | integration-tester: 5 | build: ./NAME.IntegrationTests 6 | links: 7 | - mongo 8 | - rabbitmq 9 | - sqlserver 10 | - specific-mongo 11 | - specific-rabbitmq 12 | - dummy-service 13 | - elasticsearch 14 | - specific-elasticsearch 15 | - dummy-console-kestrel 16 | environment: 17 | - LATEST_MONGO_HOSTNAME=mongo 18 | - LATEST_RABBIT_HOSTNAME=rabbitmq 19 | - LATEST_SQLSERVER_HOSTNAME=sqlserver 20 | - SPECIFIC_MONGO_HOSTNAME=specific-mongo 21 | - SPECIFIC_MONGO_VERSION=3.0.14 22 | - SPECIFIC_RABBIT_HOSTNAME=specific-rabbitmq 23 | - SPECIFIC_RABBIT_VERSION=3.6.5 24 | - SPECIFIC_SERVICE_HOSTNAME=dummy-service 25 | - SPECIFIC_SERVICE_VERSION=1.0.0 26 | - SPECIFIC_KESTREL_SELFHOST_HOSTNAME=dummy-console-kestrel 27 | - SPECIFIC_KESTREL_SELFHOST_VERSION=1.0.0 28 | - OPERATING_SYSTEM=debian 29 | - RUNNING_ON_DOCKER=true 30 | - LATEST_ELASTICSEARCH_HOSTNAME=elasticsearch 31 | - SPECIFIC_ELASTICSEARCH_HOSTNAME=specific-elasticsearch 32 | - SPECIFIC_ELASTICSEARCH_VERSION=5.5.1 33 | volumes: 34 | - ../Output/Artifacts/NuGets/Release:/integration/nugets 35 | - ../Output/IntegrationTestsResults:/integration/TestResults 36 | depends_on: 37 | - mongo 38 | - rabbitmq 39 | - sqlserver 40 | - specific-mongo 41 | - specific-rabbitmq 42 | - dummy-service 43 | - elasticsearch 44 | - specific-elasticsearch 45 | - dummy-console-kestrel 46 | dummy-service: 47 | build: ./NAME.DummyService 48 | environment: 49 | - RUNNING_ON_DOCKER=true 50 | volumes: 51 | - ../Output/Artifacts/NuGets/Release:/service/nugets 52 | expose: 53 | - "5000" 54 | dummy-console-kestrel: 55 | build: ./NAME.DummyConsole.Kestrel 56 | environment: 57 | - RUNNING_ON_DOCKER=true 58 | volumes: 59 | - ../Output/Artifacts/NuGets/Release:/service/nugets 60 | expose: 61 | - "40500" 62 | mongo: 63 | image: mongo 64 | expose: 65 | - "27017" 66 | specific-mongo: 67 | image: mongo:3.0.14 68 | expose: 69 | - "27017" 70 | rabbitmq: 71 | image: rabbitmq 72 | expose: 73 | - "5672" 74 | specific-rabbitmq: 75 | image: rabbitmq:3.6.5 76 | expose: 77 | - "5672" 78 | sqlserver: 79 | image: microsoft/mssql-server-linux:2017-GA 80 | expose: 81 | - "1433" 82 | environment: 83 | - SA_PASSWORD=W1#llnotbeused 84 | - ACCEPT_EULA=Y 85 | elasticsearch: 86 | image: docker.elastic.co/elasticsearch/elasticsearch:5.6.3 87 | expose: 88 | - "9200" 89 | environment: 90 | - xpack.security.enabled=false 91 | specific-elasticsearch: 92 | image: docker.elastic.co/elasticsearch/elasticsearch:5.5.1 93 | expose: 94 | - "9200" 95 | environment: 96 | - xpack.security.enabled=false 97 | --------------------------------------------------------------------------------