├── .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