diff --git a/Example/.env b/Example/.env index 1da2129..6c570ca 100644 --- a/Example/.env +++ b/Example/.env @@ -1 +1 @@ -DOCKER_REGISTRY=typeedge.azurecr.io/ \ No newline at end of file +DOCKER_REGISTRY=typeedge.azurecr.io/ \ No newline at end of file diff --git a/Example/Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.csproj b/Example/Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.csproj index d9d21e8..0eb4073 100644 --- a/Example/Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.csproj +++ b/Example/Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.csproj @@ -13,7 +13,7 @@ - + diff --git a/Example/Modules/NormalizeTemperatureModule/Program.cs b/Example/Modules/NormalizeTemperatureModule/Program.cs index 28dcba5..a594fe6 100644 --- a/Example/Modules/NormalizeTemperatureModule/Program.cs +++ b/Example/Modules/NormalizeTemperatureModule/Program.cs @@ -7,7 +7,7 @@ namespace Modules { public static async Task Main(string[] args) { - await Startup.DockerEntryPoint(args); + await Startup.DockerEntryPoint(args); } } } \ No newline at end of file diff --git a/Example/Modules/NormalizeTemperatureModule/Properties/launchSettings.json b/Example/Modules/NormalizeTemperatureModule/Properties/launchSettings.json deleted file mode 100644 index 65c97e1..0000000 --- a/Example/Modules/NormalizeTemperatureModule/Properties/launchSettings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "profiles": { - "NormalizeTemperatureModule": { - "commandName": "Project", - "environmentVariables": { - "ModuleName": "normalizetemperaturemodule" - } - } - } -} \ No newline at end of file diff --git a/Example/Modules/TemperatureModule/Properties/launchSettings.json b/Example/Modules/TemperatureModule/Properties/launchSettings.json deleted file mode 100644 index 8611fbc..0000000 --- a/Example/Modules/TemperatureModule/Properties/launchSettings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "profiles": { - "TemperatureModule": { - "commandName": "Project", - "environmentVariables": { - "ModuleName": "Temperature" - } - } - } -} \ No newline at end of file diff --git a/Example/Modules/TemperatureModule/TemperatureModule.csproj b/Example/Modules/TemperatureModule/TemperatureModule.csproj index d9d21e8..0eb4073 100644 --- a/Example/Modules/TemperatureModule/TemperatureModule.csproj +++ b/Example/Modules/TemperatureModule/TemperatureModule.csproj @@ -13,7 +13,7 @@ - + diff --git a/Example/Thermostat.Emulator/Program.cs b/Example/Thermostat.Emulator/Program.cs index 87c4aab..e96f55d 100644 --- a/Example/Thermostat.Emulator/Program.cs +++ b/Example/Thermostat.Emulator/Program.cs @@ -4,7 +4,7 @@ using Microsoft.Azure.IoT.TypeEdge.Host; using Microsoft.Extensions.Configuration; using Modules; using ThermostatApplication.Modules; -using Microsoft.Azure.IoT.TypeEdge.Host.DovEnv; +using Microsoft.Azure.IoT.TypeEdge.DovEnv; namespace ThermostatApplication { diff --git a/Example/Thermostat.Emulator/Thermostat.Emulator.csproj b/Example/Thermostat.Emulator/Thermostat.Emulator.csproj index 8ab1b7a..4156531 100644 --- a/Example/Thermostat.Emulator/Thermostat.Emulator.csproj +++ b/Example/Thermostat.Emulator/Thermostat.Emulator.csproj @@ -18,7 +18,7 @@ - + diff --git a/Example/Thermostat.Emulator/appsettings_thermostat.json b/Example/Thermostat.Emulator/appsettings_thermostat.json index 32fa5c7..463b745 100644 --- a/Example/Thermostat.Emulator/appsettings_thermostat.json +++ b/Example/Thermostat.Emulator/appsettings_thermostat.json @@ -2,6 +2,6 @@ "TypeEdgeHost": { "IotHubConnectionString": "HostName=iotedgedev-iothub-7389d7.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=UqshG8knBj9ZG5J8tM9S7rTSQI4Ho1L5eWPz3Subkbo=", "DeviceId": "type-edge-dev8", - "PrintDeploymentJson": "true" + "PrintDeploymentJson": "true" } } \ No newline at end of file diff --git a/Example/Thermostat.ServiceApp/Thermostat.ServiceApp.csproj b/Example/Thermostat.ServiceApp/Thermostat.ServiceApp.csproj index 27ce554..2b96526 100644 --- a/Example/Thermostat.ServiceApp/Thermostat.ServiceApp.csproj +++ b/Example/Thermostat.ServiceApp/Thermostat.ServiceApp.csproj @@ -12,7 +12,7 @@ - + diff --git a/Example/Thermostat.Shared/Thermostat.Shared.csproj b/Example/Thermostat.Shared/Thermostat.Shared.csproj index 4945c18..1c81ce1 100644 --- a/Example/Thermostat.Shared/Thermostat.Shared.csproj +++ b/Example/Thermostat.Shared/Thermostat.Shared.csproj @@ -10,7 +10,7 @@ - + diff --git a/Example/addPrivateSource.bat b/Example/addPrivateSource.bat new file mode 100644 index 0000000..45fdf50 --- /dev/null +++ b/Example/addPrivateSource.bat @@ -0,0 +1,49 @@ +@echo off +IF "%1"=="" GOTO HAVE_USERNAME +IF "%2"=="" GOTO HAVE_PASSWORD + + +if exist nuget.exe ( + echo nuget.exe found +) else ( + echo downloading nuget.exe from https://www.nuget.org/nuget.exe + + Powershell.exe wget -outf nuget.exe https://nuget.org/nuget.exe + if not exist .\nuget.exe ( + echo Error: nuget does not exist. + exit /b 1 + ) +) + + +echo Adding the private nuget packages feed "private-typeedge-feed" +nuget.exe sources Add -Name "private-typeedge-feed" -Source "https://msblox-03.pkgs.visualstudio.com/_packaging/private-nuget-feed/nuget/v3/index.json" -StorePasswordInClearText -ConfigFile NuGet.Config -UserName "%1" -Password "%2" + +if errorlevel 1 ( + echo Failed, trying to remove an existing record first .. + echo Removing the private "private-typeedge-feed" .. + nuget.exe sources Remove -Name "private-typeedge-feed" + echo Adding the private nuget packages feed "private-typeedge-feed" + nuget.exe sources Add -Name "private-typeedge-feed" -Source "https://msblox-03.pkgs.visualstudio.com/_packaging/private-nuget-feed/nuget/v3/index.json" -StorePasswordInClearText -ConfigFile NuGet.Config -UserName "%1" -Password "%2" + if errorlevel 0 ( + echo Success! + ) +) + +if exist nuget.exe ( + del nuget.exe /q +) + +exit /b 0 + + +:HAVE_USERNAME +echo Your Git credentials username is required +exit /b 1 + +:HAVE_PASSWORD +echo Your Git credentials password is required +exit /b 1 + +:exit +echo exiting.. \ No newline at end of file diff --git a/Example/docker-compose.dcproj b/Example/docker-compose.dcproj index cc713c3..4eee851 100644 --- a/Example/docker-compose.dcproj +++ b/Example/docker-compose.dcproj @@ -6,6 +6,7 @@ 1373dbdc-dc13-429e-8c17-2e4d85cf42ba + docker-compose.yml diff --git a/Example/docker-compose.yml b/Example/docker-compose.yml index b60cb89..fdca704 100644 --- a/Example/docker-compose.yml +++ b/Example/docker-compose.yml @@ -1,22 +1,29 @@ version: '3.4' +volumes: + env: + services: - - normalizetemperaturemodule: - image: ${DOCKER_REGISTRY}normalizetemperature - build: - context: . - dockerfile: Modules/NormalizeTemperatureModule/Dockerfile - - - temperaturemodule: - image: ${DOCKER_REGISTRY}temperature - build: - context: . - dockerfile: Modules/TemperatureModule/Dockerfile - thermostat.emulator: image: ${DOCKER_REGISTRY}thermostatemulator build: context: . dockerfile: Thermostat.Emulator/Dockerfile + volumes: + - env:/env + + normalizetemperaturemodule: + image: ${DOCKER_REGISTRY}normalizetemperaturemodule + build: + context: . + dockerfile: Modules/NormalizeTemperatureModule/Dockerfile + volumes: + - env:/env + + temperaturemodule: + image: ${DOCKER_REGISTRY}temperaturemodule + build: + context: . + dockerfile: Modules/TemperatureModule/Dockerfile + volumes: + - env:/env diff --git a/Example/nuget.exe b/Example/nuget.exe deleted file mode 100644 index f74bfff..0000000 Binary files a/Example/nuget.exe and /dev/null differ diff --git a/Microsoft.Azure.IoT.TypeEdge-WithExample.sln b/Microsoft.Azure.IoT.TypeEdge-WithExample.sln index 781e290..d8df084 100644 --- a/Microsoft.Azure.IoT.TypeEdge-WithExample.sln +++ b/Microsoft.Azure.IoT.TypeEdge-WithExample.sln @@ -12,18 +12,31 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{F2FF1756-9AAF-411B-8B54-3829EAC21515}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TemperatureModule", "Example\Modules\TemperatureModule\TemperatureModule.csproj", "{48302C68-971D-414F-A29D-742F79415D74}" + ProjectSection(ProjectDependencies) = postProject + {54587D56-7C22-4084-9321-84D57C2F6ECB} = {54587D56-7C22-4084-9321-84D57C2F6ECB} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NormalizeTemperatureModule", "Example\Modules\NormalizeTemperatureModule\NormalizeTemperatureModule.csproj", "{30A335A6-47C9-435A-BA23-50988EAF2C33}" + ProjectSection(ProjectDependencies) = postProject + {54587D56-7C22-4084-9321-84D57C2F6ECB} = {54587D56-7C22-4084-9321-84D57C2F6ECB} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thermostat.Shared", "Example\Thermostat.Shared\Thermostat.Shared.csproj", "{45F97F43-7C75-49B8-8525-7F0E9C7B9FB7}" ProjectSection(ProjectDependencies) = postProject + {54587D56-7C22-4084-9321-84D57C2F6ECB} = {54587D56-7C22-4084-9321-84D57C2F6ECB} {E738845B-4D98-4CB9-BDA4-F83193FE81B5} = {E738845B-4D98-4CB9-BDA4-F83193FE81B5} {6F13F88C-B271-4DA6-9A35-5FD7FEADD3A3} = {6F13F88C-B271-4DA6-9A35-5FD7FEADD3A3} EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thermostat.Emulator", "Example\Thermostat.Emulator\Thermostat.Emulator.csproj", "{2076DDEF-8EE3-4BC1-BF79-1C1F62A8719D}" + ProjectSection(ProjectDependencies) = postProject + {54587D56-7C22-4084-9321-84D57C2F6ECB} = {54587D56-7C22-4084-9321-84D57C2F6ECB} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thermostat.ServiceApp", "Example\Thermostat.ServiceApp\Thermostat.ServiceApp.csproj", "{286CDAA1-5410-4322-AC1C-F35A83CDA63D}" + ProjectSection(ProjectDependencies) = postProject + {54587D56-7C22-4084-9321-84D57C2F6ECB} = {54587D56-7C22-4084-9321-84D57C2F6ECB} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.IoT.TypeEdge.Proxy", "Microsoft.Azure.IoT.TypeEdge.Proxy\Microsoft.Azure.IoT.TypeEdge.Proxy.csproj", "{E738845B-4D98-4CB9-BDA4-F83193FE81B5}" EndProject diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/.nuspec b/Microsoft.Azure.IoT.TypeEdge.Host/.nuspec index ec96a56..02ea124 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/.nuspec +++ b/Microsoft.Azure.IoT.TypeEdge.Host/.nuspec @@ -2,14 +2,14 @@ Microsoft.Azure.IoT.TypeEdge.Host - 0.1.26 + 0.1.48 paloukari paloukari false Package Description - + diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHost.cs b/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHost.cs index 88a0329..64de3fa 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHost.cs +++ b/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHost.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Autofac; using Autofac.Extensions.DependencyInjection; using Castle.DynamicProxy; -using Microsoft.Azure.Devices; +using Microsoft.Azure.Devices; using Microsoft.Azure.Devices.Common.Exceptions; using Microsoft.Azure.Devices.Edge.Agent.Core; using Microsoft.Azure.Devices.Edge.Storage; @@ -34,6 +34,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host private readonly EdgeHub _hub; private ModuleCollection _modules; private readonly TypeEdgeHostOptions _options; + private readonly bool _inContainer; public TypeEdgeHost(IConfigurationRoot configuration) @@ -53,6 +54,8 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host _hub = new EdgeHub(); Upstream = new Upstream(_hub); + + _inContainer = File.Exists(@"/.dockerenv"); } public Upstream Upstream { get; set; } @@ -74,7 +77,8 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host public void Build() { - //setup the container + CleanUp(); + BuildContainer(); _modules = CreateModules(); @@ -86,6 +90,14 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host BuildHub(deviceSasKey); } + private void CleanUp() + { + if (!_inContainer || !Directory.Exists(TypeEdge.Constants.ComposeConfigurationPath)) + return; + foreach (var file in Directory.EnumerateFiles(TypeEdge.Constants.ComposeConfigurationPath)) + File.Delete(file); + } + public async Task RunAsync() { @@ -93,9 +105,11 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host { _hub.RunAsync() }; + //start all modules - foreach (var module in _modules) - tasks.Add(module.InternalRunAsync()); + if (!_inContainer) + foreach (var module in _modules) + tasks.Add(module.InternalRunAsync()); await Task.WhenAll(tasks.ToArray()); } @@ -164,22 +178,49 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host private void ConfigureModules() { + var certificatePath = @"Certificates/edge-device-ca/cert/edge-device-ca-root.cert.pem"; var currentLocation = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + + Environment.SetEnvironmentVariable(Devices.Edge.Agent.Core.Constants.EdgeModuleCaCertificateFileKey, + Path.Combine(currentLocation, + certificatePath)); + foreach (var module in _modules) { var moduleConnectionString = GetModuleConnectionStringAsync(_options.IotHubConnectionString, _options.DeviceId, module.Name) .Result; - Environment.SetEnvironmentVariable(Devices.Edge.Agent.Core.Constants.EdgeHubConnectionStringKey, - moduleConnectionString); - Environment.SetEnvironmentVariable(Devices.Edge.Agent.Core.Constants.EdgeModuleCaCertificateFileKey, - Path.Combine(currentLocation, @"Certificates/edge-device-ca/cert/edge-device-ca-root.cert.pem")); - var moduleConfiguration = new ConfigurationBuilder() - .AddEnvironmentVariables() - .Build(); + if (_inContainer) + { + System.Console.WriteLine("Emulator running in docker-compose mode."); - module.InternalConfigure(moduleConfiguration); + const string envPath = TypeEdge.Constants.ComposeConfigurationPath; + var path = Path.Combine(envPath, $"{module.Name}.env"); + var certPath = Path.Combine(envPath, certificatePath); + + var dotenvData = $"{Devices.Edge.Agent.Core.Constants.EdgeHubConnectionStringKey}={moduleConnectionString}"; + dotenvData += $"{Environment.NewLine}{Devices.Edge.Agent.Core.Constants.EdgeModuleCaCertificateFileKey}={certPath}"; + + if (!Directory.Exists(Path.GetDirectoryName(certPath))) + Directory.CreateDirectory(Path.GetDirectoryName(certPath)); + + if (!File.Exists(certPath)) + File.Copy(Path.Combine(currentLocation, certificatePath), certPath); + + File.WriteAllText(path, dotenvData); + } + else + { + Environment.SetEnvironmentVariable(Devices.Edge.Agent.Core.Constants.EdgeHubConnectionStringKey, + moduleConnectionString); + + var moduleConfiguration = new ConfigurationBuilder() + .AddEnvironmentVariables() + .Build(); + + module.InternalConfigure(moduleConfiguration); + } } } @@ -210,7 +251,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host try { var device = await registryManager.AddDeviceAsync( - new Device(_options.DeviceId) {Capabilities = new DeviceCapabilities {IotEdge = true}}); + new Device(_options.DeviceId) { Capabilities = new DeviceCapabilities { IotEdge = true } }); sasKey = device.Authentication.SymmetricKey.PrimaryKey; } catch (DeviceAlreadyExistsException) @@ -231,7 +272,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host var modulesConfig = configurationContent.ModuleContent["$edgeAgent"].TargetContent["modules"] as JObject; - var dockerRegistry = Environment.GetEnvironmentVariable("DOCKER_REGISTRY") ?? ""; + var dockerRegistry = _configuration.GetValue("DOCKER_REGISTRY") ?? ""; foreach (var module in _modules) { @@ -265,8 +306,8 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host var routes = new Dictionary(); foreach (var module in _modules) - foreach (var route in module.Routes) - routes[$"route{routes.Count}"] = route; + foreach (var route in module.Routes) + routes[$"route{routes.Count}"] = route; foreach (var route in _hub.Routes) routes[$"route{routes.Count}"] = route; diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHostOptions.cs b/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHostOptions.cs index 331e2c3..14213d2 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHostOptions.cs +++ b/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHostOptions.cs @@ -1,4 +1,6 @@ -using Serilog.Events; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Serilog.Events; namespace Microsoft.Azure.IoT.TypeEdge.Host { @@ -7,7 +9,9 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host public string IotHubConnectionString { get; set; } public string DeviceId { get; set; } public LogEventLevel? RuntimeLogLevel { get; set; } - public bool? PrintDeploymentJson { get; set; } + + [JsonConverter(typeof(StringEnumConverter))] + public RunningEnvironment? Environment { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge.Proxy/Microsoft.Azure.IoT.TypeEdge.Proxy.csproj b/Microsoft.Azure.IoT.TypeEdge.Proxy/Microsoft.Azure.IoT.TypeEdge.Proxy.csproj index 09adbdb..fee7375 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Proxy/Microsoft.Azure.IoT.TypeEdge.Proxy.csproj +++ b/Microsoft.Azure.IoT.TypeEdge.Proxy/Microsoft.Azure.IoT.TypeEdge.Proxy.csproj @@ -2,7 +2,7 @@ Microsoft.Azure.IoT.TypeEdge.Proxy - 0.1.26 + 0.1.48 paloukari Microsoft diff --git a/Microsoft.Azure.IoT.TypeEdge/Constants.cs b/Microsoft.Azure.IoT.TypeEdge/Constants.cs index 10b76c1..d62f3cd 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Constants.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Constants.cs @@ -4,6 +4,7 @@ { public const string ConfigFileName = "appsettings_compose.json"; public const string EdgeHubConnectionStringKey = "EdgeHubConnectionString"; - public const string ModuleNameConfigName = "ModuleName"; + public const string ModuleNameConfigName = "moduleName"; + public const string ComposeConfigurationPath = "/env"; } } \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/Dotenv.cs b/Microsoft.Azure.IoT.TypeEdge/DovEnv/Dotenv.cs similarity index 98% rename from Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/Dotenv.cs rename to Microsoft.Azure.IoT.TypeEdge/DovEnv/Dotenv.cs index 08c6be0..df33a49 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/Dotenv.cs +++ b/Microsoft.Azure.IoT.TypeEdge/DovEnv/Dotenv.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; -namespace Microsoft.Azure.IoT.TypeEdge.Host.DovEnv +namespace Microsoft.Azure.IoT.TypeEdge.DovEnv { public class Dotenv { diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/DotenvConfigurationProvider.cs b/Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvConfigurationProvider.cs similarity index 91% rename from Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/DotenvConfigurationProvider.cs rename to Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvConfigurationProvider.cs index a72cf0c..c3752a6 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/DotenvConfigurationProvider.cs +++ b/Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvConfigurationProvider.cs @@ -1,7 +1,7 @@ using System.IO; using Microsoft.Extensions.Configuration; -namespace Microsoft.Azure.IoT.TypeEdge.Host.DovEnv +namespace Microsoft.Azure.IoT.TypeEdge.DovEnv { public class DotenvConfigurationProvider : FileConfigurationProvider { diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/DotenvConfigurationSource.cs b/Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvConfigurationSource.cs similarity index 87% rename from Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/DotenvConfigurationSource.cs rename to Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvConfigurationSource.cs index e1f020a..d18aca6 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/DotenvConfigurationSource.cs +++ b/Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvConfigurationSource.cs @@ -1,6 +1,6 @@ using Microsoft.Extensions.Configuration; -namespace Microsoft.Azure.IoT.TypeEdge.Host.DovEnv +namespace Microsoft.Azure.IoT.TypeEdge.DovEnv { public class DotenvConfigurationSource : FileConfigurationSource { diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/DotenvExtension.cs b/Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvExtension.cs similarity index 86% rename from Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/DotenvExtension.cs rename to Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvExtension.cs index 2093481..346520b 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/DotenvExtension.cs +++ b/Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvExtension.cs @@ -3,8 +3,9 @@ using System.Collections.Generic; using System.IO; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.FileProviders; +using PhysicalFileProvider = Microsoft.Azure.IoT.TypeEdge.DovEnv.FileProvider.PhysicalFileProvider; -namespace Microsoft.Azure.IoT.TypeEdge.Host.DovEnv +namespace Microsoft.Azure.IoT.TypeEdge.DovEnv { public static class DotenvExtension { @@ -67,17 +68,18 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host.DovEnv //-- // The below is still needed for .NET Core 1.x //-- - var fileExists = false; - foreach (var basePath in basePaths) - { - var testPath = string.Join("/", new string[] { basePath, path }); - if (File.Exists(testPath)) + var fileExists = path.StartsWith('/') && File.Exists(path); + if (!fileExists) + foreach (var basePath in basePaths) { + var testPath = string.Join("/", new string[] { basePath, path }); + Console.WriteLine($"DotEnv: checking for {testPath}"); + if (!File.Exists(testPath)) + continue; fileExists = true; path = testPath; break; } - } if (!fileExists && !optional) { throw new Exception($"The .env configuration file '{path}' was not found"); @@ -86,7 +88,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host.DovEnv { // Real PhysicalFileProvider has a bug that don't allow dot files: // https://github.com/aspnet/FileSystem/issues/232 - provider = new FileProvider.PhysicalFileProvider(Path.GetDirectoryName(path)); + provider = new PhysicalFileProvider(Path.GetDirectoryName(path)); path = Path.GetFileName(path); } } diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/FileProvider/CompositeChangeToken.cs b/Microsoft.Azure.IoT.TypeEdge/DovEnv/FileProvider/CompositeChangeToken.cs similarity index 98% rename from Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/FileProvider/CompositeChangeToken.cs rename to Microsoft.Azure.IoT.TypeEdge/DovEnv/FileProvider/CompositeChangeToken.cs index 996f0d0..bd9b321 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/FileProvider/CompositeChangeToken.cs +++ b/Microsoft.Azure.IoT.TypeEdge/DovEnv/FileProvider/CompositeChangeToken.cs @@ -4,7 +4,7 @@ using System.Diagnostics; using System.Threading; using Microsoft.Extensions.Primitives; -namespace Microsoft.Azure.IoT.TypeEdge.Host.DovEnv.FileProvider +namespace Microsoft.Azure.IoT.TypeEdge.DovEnv.FileProvider { public class CompositeChangeToken : IChangeToken { diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/FileProvider/PhysicalFileProvider.cs b/Microsoft.Azure.IoT.TypeEdge/DovEnv/FileProvider/PhysicalFileProvider.cs similarity index 98% rename from Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/FileProvider/PhysicalFileProvider.cs rename to Microsoft.Azure.IoT.TypeEdge/DovEnv/FileProvider/PhysicalFileProvider.cs index 9d9ce22..0646ea4 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/FileProvider/PhysicalFileProvider.cs +++ b/Microsoft.Azure.IoT.TypeEdge/DovEnv/FileProvider/PhysicalFileProvider.cs @@ -5,8 +5,9 @@ using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders.Internal; using Microsoft.Extensions.FileProviders.Physical; using Microsoft.Extensions.Primitives; +using PhysicalFilesWatcher = Microsoft.Azure.IoT.TypeEdge.DovEnv.FileProvider.PhysicalFilesWatcher; -namespace Microsoft.Azure.IoT.TypeEdge.Host.DovEnv.FileProvider +namespace Microsoft.Azure.IoT.TypeEdge.DovEnv.FileProvider { public class PhysicalFileProvider : IFileProvider, IDisposable { diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/FileProvider/PhysicalFileWatcher.cs b/Microsoft.Azure.IoT.TypeEdge/DovEnv/FileProvider/PhysicalFileWatcher.cs similarity index 99% rename from Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/FileProvider/PhysicalFileWatcher.cs rename to Microsoft.Azure.IoT.TypeEdge/DovEnv/FileProvider/PhysicalFileWatcher.cs index c67cb31..1fdbd92 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/DovEnv/FileProvider/PhysicalFileWatcher.cs +++ b/Microsoft.Azure.IoT.TypeEdge/DovEnv/FileProvider/PhysicalFileWatcher.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.FileProviders.Physical; using Microsoft.Extensions.FileSystemGlobbing; using Microsoft.Extensions.Primitives; -namespace Microsoft.Azure.IoT.TypeEdge.Host.DovEnv.FileProvider +namespace Microsoft.Azure.IoT.TypeEdge.DovEnv.FileProvider { public class PhysicalFilesWatcher : IDisposable { diff --git a/Microsoft.Azure.IoT.TypeEdge/Microsoft.Azure.IoT.TypeEdge.csproj b/Microsoft.Azure.IoT.TypeEdge/Microsoft.Azure.IoT.TypeEdge.csproj index 9c6b463..aea6254 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Microsoft.Azure.IoT.TypeEdge.csproj +++ b/Microsoft.Azure.IoT.TypeEdge/Microsoft.Azure.IoT.TypeEdge.csproj @@ -2,7 +2,7 @@ Microsoft.Azure.IoT.TypeEdge - 0.1.26 + 0.1.48 paloukari Microsoft ../../TypeEdgeNuGets diff --git a/Microsoft.Azure.IoT.TypeEdge/Modules/EdgeModule.cs b/Microsoft.Azure.IoT.TypeEdge/Modules/EdgeModule.cs index c11a50e..b4fdb97 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Modules/EdgeModule.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Modules/EdgeModule.cs @@ -11,7 +11,6 @@ using System.Threading.Tasks; using Microsoft.Azure.Devices.Client; using Microsoft.Azure.Devices.Client.Transport.Mqtt; using Microsoft.Azure.Devices.Shared; -using Microsoft.Azure.IoT.TypeEdge.Attributes; using Microsoft.Azure.IoT.TypeEdge.Enums; using Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints; using Microsoft.Azure.IoT.TypeEdge.Modules.Enums; @@ -71,7 +70,6 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules internal virtual async Task GetTwinAsync(string name) where T : IModuleTwin, new() - { var typeTwin = Activator.CreateInstance(); typeTwin.SetTwin(name, await _ioTHubModuleClient.GetTwinAsync()); @@ -151,7 +149,11 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules internal CreationResult InternalConfigure(IConfigurationRoot configuration) { Console.WriteLine($"{Name}:InternalConfigure called"); - _connectionString = configuration.GetValue(Constants.EdgeHubConnectionStringKey); + + _connectionString = configuration.GetValue($"{Constants.EdgeHubConnectionStringKey}"); + if (string.IsNullOrEmpty(_connectionString)) + throw new ArgumentException($"Missing {Constants.EdgeHubConnectionStringKey} in configuration for {Name}"); + // Cert verification is not yet fully functional when using Windows OS for the container var bypassCertVerification = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); diff --git a/Microsoft.Azure.IoT.TypeEdge/Startup.cs b/Microsoft.Azure.IoT.TypeEdge/Startup.cs index b13beed..aff12d2 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Startup.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Startup.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Loader; @@ -8,10 +9,12 @@ using Autofac; using Autofac.Extensions.DependencyInjection; using Castle.DynamicProxy; using Microsoft.Azure.IoT.TypeEdge.Attributes; +using Microsoft.Azure.IoT.TypeEdge.DovEnv; using Microsoft.Azure.IoT.TypeEdge.Modules; using Microsoft.Azure.IoT.TypeEdge.Proxy; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using static System.String; namespace Microsoft.Azure.IoT.TypeEdge { @@ -31,22 +34,65 @@ namespace Microsoft.Azure.IoT.TypeEdge .AddCommandLine(args) .Build(); - var moduleName = configuration.GetValue(Constants.ModuleNameConfigName); - //todo: throw or warn here? - if (string.IsNullOrEmpty(moduleName)) + if (IsNullOrEmpty(moduleName)) { Console.WriteLine($"WARN:No {Constants.ModuleNameConfigName} in configuration. "); - Console.WriteLine("Exiting..."); - return; - //throw new ArgumentException($"No moduleName in arguments"); + + moduleName = DiscoverModuleName(); + if (IsNullOrEmpty(moduleName)) + { + Console.WriteLine("Exiting..."); + return; + //throw new ArgumentException($"No moduleName in arguments"); + } } var (moduleType, _) = GetModuleTypes(moduleName); if (moduleType == null) - throw new ArgumentException($"No module callled {moduleName} in calling assembly"); + throw new ArgumentException($"No module called {moduleName} in calling assembly"); + + var connectionString = configuration.GetValue($"{Constants.EdgeHubConnectionStringKey}"); + + if (IsNullOrEmpty(connectionString)) + { + + //check the file system, we are in docker-compose mode + var fileName = Path.Combine(Constants.ComposeConfigurationPath, $"{moduleName}.env"); + var remainingSeconds = 30; + while (remainingSeconds-- > 0) + { + if (File.Exists(fileName)) + { + configuration = new ConfigurationBuilder() + .AddEnvironmentVariables() + .AddCommandLine(args) + .AddDotenvFile(fileName) + .Build(); + File.Delete(fileName); + break; + } + + var directory = Path.GetDirectoryName(fileName); + foreach (var file in Directory.EnumerateFiles(directory)) + { + Console.WriteLine(file); + } + + Console.WriteLine($"{moduleName}:{fileName} does not exist. Retrying in 1 sec."); + Thread.Sleep(1000); + } + + if (remainingSeconds < 0) + { + Console.WriteLine($"{moduleName}:No {moduleName}.env found."); + Console.WriteLine($"{moduleName}:Exiting..."); + return; + } + } + containerBuilder.RegisterType(moduleType); @@ -81,6 +127,20 @@ namespace Microsoft.Azure.IoT.TypeEdge await WhenCancelled(cts.Token); } + private static string DiscoverModuleName() + { + var assembly = Assembly.GetEntryAssembly(); + var moduleType = assembly.GetTypes().SingleOrDefault(t => + t.GetInterfaces().SingleOrDefault(i => + i.GetCustomAttribute(typeof(TypeModuleAttribute), true) != null) != null); + + if (moduleType == null) + return null; + + var moduleInterfaceType = moduleType.GetProxyInterface(); + return moduleInterfaceType.Name.Substring(1).ToLower(); + } + public static Task WhenCancelled(CancellationToken cancellationToken) { var tcs = new TaskCompletionSource(); @@ -105,7 +165,7 @@ namespace Microsoft.Azure.IoT.TypeEdge var moduleType = assembly.GetTypes().SingleOrDefault(t => t.GetInterfaces().SingleOrDefault(i => i.GetCustomAttribute(typeof(TypeModuleAttribute), true) != null && - string.Equals(i.Name.Substring(1), moduleName, StringComparison.CurrentCultureIgnoreCase)) != null); + String.Equals(i.Name.Substring(1), moduleName, StringComparison.CurrentCultureIgnoreCase)) != null); if (moduleType == null) { diff --git a/NuGet.Config b/NuGet.Config index 4ee692e..a9beddc 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -14,6 +14,7 @@ + diff --git a/README.md b/README.md index 698f0ea..fd65898 100644 --- a/README.md +++ b/README.md @@ -1,111 +1,137 @@ # Azure IoT TypeEdge -The **Azure IoT TypeEdge** introduces a strongly typed flavor of the inherently loosely coupled vanilla [Azure IoT Edge](https:/azure.microsoft.com/en-us/services/iot-edge/). +The **Azure IoT TypeEdge** introduces a strongly-typed flavor of the inherently loosely coupled vanilla [Azure IoT Edge](https:/azure.microsoft.com/en-us/services/iot-edge/). -Specifically: +Specifically, **TypeEdge**: -- It removes all configuration burden from an IoT Edge application, because configuration can be now automatically generated by code reflection. -- Introduces compile time types checking across all modules -- It adds the ability to **emulate an IoT Edge device on the development environment**, by running all components in memory, no containers involved -- It simplifies the IoT Edge development down to an single F5 experience +- Removes all configuration burden from an IoT Edge application, because configuration can be now automatically generated. +- Introduces compile-time types checking across all modules +- Adds the ability to **emulate an IoT Edge device in-memory** with no containers involved +- Simplifies the IoT Edge development, down to an single F5 experience -## Initial Setup +## Prerequisites + +The minimum requirements to get started with **TypeEdge** are: + - The latest [.NET Core SDK](https://github.com/dotnet/core/blob/master/release-notes/download-archives/2.1.0-download.md) (version 2.1.300). To find your current version, run +`dotnet --version` + - An [Azure IoT Hub](https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-create-through-portal) + +To be able to publish your application, you will also need: + - [Docker](https://docs.docker.com/engine/installation/) + - An [Azure Container Registry](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-portal), or any other secure container registry. + - Temporarily, you'll need your git credentials to login [to the private packages feed.](https://msblox-03.visualstudio.com/csetypeedge) -Make sure you have [Docker](https://docs.docker.com/engine/installation/), the latest [.NET Core SDK](https://github.com/dotnet/core/blob/master/release-notes/download-archives/2.1.0-download.md) (version 2.1.300) and your git credentials to login [here](https://msblox-03.visualstudio.com/csetypeedge) - - -> Note: To get your git credentials, navigate to the [VSTS repo](https://msblox-03.visualstudio.com/csetypeedge) and under **"clone to your computer"** section, click **"Generate Git Credentials"**. - - -You will need also an [Azure IoT Hub](https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-create-through-portal) and an [Azure Container Registry](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-portal), or any other secure container registry. - -## QuickStart -Here is the quickest way to get started with **TypeEdge**. In this quick start you will create an IoT Edge application with two modules and run it in the IoT Edge emulator: +## Create a new **TypeEdge** application +Here is the quickest way to get started with **TypeEdge**. In this quick start you will create an IoT Edge application with two modules and run it in the emulator: 1. Install the TypeEdge .NET Core solution template. Just type: ``` dotnet new -i TypeEdge.Application ``` - >**Note:** If you already installed the template and you want to **upgrade to a newer template version**, you need to clear the dotnet http and template cache + >**Note:** to **upgrade to a newer template version**, you need to clear the dotnet http and template cache first ``` dotnet nuget locals http-cache --clear dotnet new --debug:reinit ``` -2. Copy the **iothubowner connection string** from your development Azure **IoT Hub**. +1. Copy the **iothubowner** connection string from your Azure **IoT Hub**. > The **iothubowner** is required because TypeEdge needs to provision a new device with the generated deployment configuration. 1. Create a new IoT TypeEdge application: - > You can choose the TypeEdge application and modules names of this template. In the example below, the application is called **Thermostat**, and the two modules are called **SensorModule** and **PreprocessorModule**. These names will be used as class names, so **Pascal casing** is suggested. + > You can choose the TypeEdge application and modules names. In the example below, the application is called **Thermostat**, and the two modules are called **SensorModule** and **PreprocessorModule**. These names will be used as class names, so **Pascal casing** is suggested. ``` dotnet new typeedgeapp -n Thermostat -m1 SensorModule -m2 PreprocessorModule -cs "YOUR_IOTHUBOWNER_CONNECTION" -cr YOUR_CONTAINER_REGISTRY ``` - >Note: a localhost registry will not work in this version. - -1. Temporary step: - - Navigate inside the root folder to add the private packages source. Then, **add your git credentials to the command below** and run it. This will download nuget.exe and add the private packages source in your solution. - ``` - cd Thermostat - addPrivateSource.bat USERNAME PASSWORD - ``` -3. Open in VS Code/Visual Studio 2017 and hit F5: - - ``` - code . - ``` - ..or run it in the command line: - ``` - dotnet build Thermostat.sln - cd Thermostat.Emulator - dotnet run - ``` + >Note: a localhost registry is not supported at the moment. - > Note: You should see now the Edge Hub starting up.. -![](images/IoTEdge.png) .. and the messages flowing in .. ![](images/messages.png) +## Build and debug the application + +1. Navigate in the application folder: + + cd Thermostat + +1. Open in VS Code/Visual Studio 2017 and hit F5: + + - For VS Code run + + code . + + - For VS 2017 run + + Thermostat.sln + + - To run the application in the command line (no IDE): + ``` + dotnet build Thermostat.sln + cd Thermostat.Emulator + dotnet run + ``` + + >Note: In all three cases, your application is being emulated in-memory without any containers involved. This is very useful for quick develop and test iterations. + + +You should see now the Edge Hub starting up.. + +![](images/IoTEdge.png) + +.. and the messages flowing in .. +![](images/messages.png) + +## Containers debugging + +If your modules have system dependencies and you want to debug inside the containers, you can leverage the docker support feature of VS 2017. Simply start the docker-compose project from VS 2017 to **debug your application inside the docker containers**. + + +Alternatively, you can run your application inside the containers in command line: + + docker-compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.vs.debug.yml up + +> Note: To build the docker containers, temporarily you need to [add the private NuGet feed](#feed) first. + +![](images/incontainer.png) **Congratulations!** -You just created your first **TypeEdge** application. Continue reading below to learn how to deploy this application to an IoT Device, or take the time to understand [how it works](#how). +You just created your first **TypeEdge** application. Continue reading to learn how to deploy this application to an IoT Device, or take the time to understand [how it works](#how). + +## Publish the Application + +## +1. ***Temporary step* Private packages feed:** To build the containers, you have to add the private packages source first. **Add your git credentials to the private repo** and run the below command. This will download nuget.exe and add the private packages source in your solution. + + addPrivateSource.bat USERNAME PASSWORD + +1. Now, you can build the container images: + + docker-compose build + + +1. The final step is to push these images to your docker registry. Make sure Docker can access your registry: + + docker login YOUR_REGISTRY -u YOUR_USERNAME -p YOUR_PASSWORD + + Push the images to your registry + + docker-compose push + + >Note: The registry is configured in the .env file inside the root folder. **If you edit the .env file, make sure you run the the emulator afterwards** to update the cloud IoT Edge Device deployment configuration. ## Device Deployment +1. **Get the device connection string from Azure portal**, and on the device host run: -In the application root folder, type: + iotedgectl setup --connection-string "THE_DEVICE_CONNECTION_STRING" --auto-cert-gen-force-no-passwords - docker-compose build + >Note: The device name is configured in the appsettings.json of the emulator project. **Make sure you run the emulator and rebuilt the containers if you change that name**. The emulator will provision a new device if the device does not exist. - -This will build your docker images for the device deployment. Final step is to push the images to the docker registry. - - - ->Note: You need to provide the registry credentials to docker before you can push there: - - docker login YOUR_REGISTRY -u YOUR_USERNAME -p YOUR_PASSWORD - -Push the images to your registry - - docker-compose push - ->Note: The registry is configured in the .env file inside the root folder. **Make sure you run the the emulator if you edit the .env file**, to update the cloud IoT Device deployment configuration. - -This was the final step. All IoT Edge containers are ready to be deployed to the device. - -On the device host, **get the device connection string from Azure portal**, and run: - - iotedgectl setup --connection-string "THE_DEVICE_CONNECTION_STRING" --auto-cert-gen-force-no-passwords - ->Note: The device name is configured in the appsettings.json of the emulator project. **Make sure you run the emulator and rebuilt the containers if you change that name**. The emulator will provision a new device if the device does not exist. - -if your registry requires authentication, you need to run +1. If your registry requires authentication, you need to run - iotedgectl login --address YOUR_REGISTRY_ADDRESS --username YOUR_REGISTRY_USERNAME --password YOUR_REGISTRY_PASSWORD + iotedgectl login --address YOUR_REGISTRY_ADDRESS --username YOUR_REGISTRY_USERNAME --password YOUR_REGISTRY_PASSWORD -Finally, start the runtime: +1. Finally, start the runtime: - iotedgectl start + iotedgectl start Read more [here](https://docs.microsoft.com/en-us/azure/iot-edge/quickstart#configure-the-iot-edge-runtime) about the IoT Edge device deployment. diff --git a/Templates/TypeEdgeApplication/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj b/Templates/TypeEdgeApplication/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj index 7ef2f85..a30aa08 100644 --- a/Templates/TypeEdgeApplication/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj +++ b/Templates/TypeEdgeApplication/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeApplication/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj b/Templates/TypeEdgeApplication/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj index 7ef2f85..a30aa08 100644 --- a/Templates/TypeEdgeApplication/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj +++ b/Templates/TypeEdgeApplication/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/Program.cs b/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/Program.cs index f980c73..9223781 100644 --- a/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/Program.cs +++ b/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/Program.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; +using Microsoft.Azure.IoT.TypeEdge.DovEnv; using Microsoft.Azure.IoT.TypeEdge.Host; -using Microsoft.Azure.IoT.TypeEdge.Host.DovEnv; using Microsoft.Extensions.Configuration; using TypeEdgeApplication.Shared; diff --git a/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/TypeEdgeApplication.Emulator.csproj b/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/TypeEdgeApplication.Emulator.csproj index cccd33a..e6fd97b 100644 --- a/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/TypeEdgeApplication.Emulator.csproj +++ b/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/TypeEdgeApplication.Emulator.csproj @@ -7,7 +7,7 @@ - + PreserveNewest @@ -15,7 +15,7 @@ - + diff --git a/Templates/TypeEdgeApplication/TypeEdgeApplication.Proxy/TypeEdgeApplication.Proxy.csproj b/Templates/TypeEdgeApplication/TypeEdgeApplication.Proxy/TypeEdgeApplication.Proxy.csproj index 81be686..3a70eb5 100644 --- a/Templates/TypeEdgeApplication/TypeEdgeApplication.Proxy/TypeEdgeApplication.Proxy.csproj +++ b/Templates/TypeEdgeApplication/TypeEdgeApplication.Proxy/TypeEdgeApplication.Proxy.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeApplication/TypeEdgeApplication.Shared/TypeEdgeApplication.Shared.csproj b/Templates/TypeEdgeApplication/TypeEdgeApplication.Shared/TypeEdgeApplication.Shared.csproj index a81d3be..4dde1d6 100644 --- a/Templates/TypeEdgeApplication/TypeEdgeApplication.Shared/TypeEdgeApplication.Shared.csproj +++ b/Templates/TypeEdgeApplication/TypeEdgeApplication.Shared/TypeEdgeApplication.Shared.csproj @@ -5,7 +5,7 @@ - + diff --git a/Templates/TypeEdgeApplication/docker-compose.vs.debug.yml b/Templates/TypeEdgeApplication/docker-compose.vs.debug.yml index ab0c5d5..8bd140f 100644 --- a/Templates/TypeEdgeApplication/docker-compose.vs.debug.yml +++ b/Templates/TypeEdgeApplication/docker-compose.vs.debug.yml @@ -5,4 +5,6 @@ services: image: ${DOCKER_REGISTRY}TypeEdgeApplicationEmulatorImageName build: context: . - dockerfile: TypeEdgeApplication.Emulator/Dockerfile \ No newline at end of file + dockerfile: TypeEdgeApplication.Emulator/Dockerfile + volumes: + - env:/env \ No newline at end of file diff --git a/Templates/TypeEdgeApplication/docker-compose.yml b/Templates/TypeEdgeApplication/docker-compose.yml index 26c8564..f3d7fcb 100644 --- a/Templates/TypeEdgeApplication/docker-compose.yml +++ b/Templates/TypeEdgeApplication/docker-compose.yml @@ -1,4 +1,6 @@ version: '3.4' +volumes: + env: services: TypeEdgeApplication.Emulator: @@ -6,17 +8,22 @@ services: build: context: . dockerfile: TypeEdgeApplication.Emulator/DockerfileEmpty + volumes: + - env:/env TypeEdgeModule1: image: ${DOCKER_REGISTRY}TypeEdgeModule1ImageName build: context: . dockerfile: Modules/TypeEdgeModule1/Dockerfile + volumes: + - env:/env TypeEdgeModule2: image: ${DOCKER_REGISTRY}TypeEdgeModule2ImageName build: context: . dockerfile: Modules/TypeEdgeModule2/Dockerfile - + volumes: + - env:/env diff --git a/Templates/TypeEdgeEmulator/TypeEdgeEmulator.csproj b/Templates/TypeEdgeEmulator/TypeEdgeEmulator.csproj index 7d18ace..1a43e86 100644 --- a/Templates/TypeEdgeEmulator/TypeEdgeEmulator.csproj +++ b/Templates/TypeEdgeEmulator/TypeEdgeEmulator.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeModule/TypeEdgeModule.csproj b/Templates/TypeEdgeModule/TypeEdgeModule.csproj index 0369b5c..be882b5 100644 --- a/Templates/TypeEdgeModule/TypeEdgeModule.csproj +++ b/Templates/TypeEdgeModule/TypeEdgeModule.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeProxy/TypeEdgeProxy.csproj b/Templates/TypeEdgeProxy/TypeEdgeProxy.csproj index e66f68f..178b2d3 100644 --- a/Templates/TypeEdgeProxy/TypeEdgeProxy.csproj +++ b/Templates/TypeEdgeProxy/TypeEdgeProxy.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/build/TypeEdgeEmulator/content/TypeEdgeEmulator.csproj b/Templates/build/TypeEdgeEmulator/content/TypeEdgeEmulator.csproj index 7d18ace..1a43e86 100644 --- a/Templates/build/TypeEdgeEmulator/content/TypeEdgeEmulator.csproj +++ b/Templates/build/TypeEdgeEmulator/content/TypeEdgeEmulator.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/build/TypeEdgeModule/content/TypeEdgeModule.csproj b/Templates/build/TypeEdgeModule/content/TypeEdgeModule.csproj index 0369b5c..be882b5 100644 --- a/Templates/build/TypeEdgeModule/content/TypeEdgeModule.csproj +++ b/Templates/build/TypeEdgeModule/content/TypeEdgeModule.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/build/TypeEdgeProxy/content/TypeEdgeProxy.csproj b/Templates/build/TypeEdgeProxy/content/TypeEdgeProxy.csproj index e66f68f..178b2d3 100644 --- a/Templates/build/TypeEdgeProxy/content/TypeEdgeProxy.csproj +++ b/Templates/build/TypeEdgeProxy/content/TypeEdgeProxy.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/nugetBuild.bat b/Templates/nugetBuild.bat index a3e9feb..60b771f 100644 --- a/Templates/nugetBuild.bat +++ b/Templates/nugetBuild.bat @@ -55,7 +55,7 @@ nuget.exe pack build\TypeEdgeApplication -Version %version% move /Y *.nupkg ..\..\TypeEdgeNuGets -rem nuget.exe push ..\..\TypeEdgeNuGets\*%version%.nupkg -ApiKey VSTS +nuget.exe push ..\..\TypeEdgeNuGets\*%version%.nupkg -ApiKey VSTS dotnet nuget locals http-cache --clear dotnet new --debug:reinit diff --git a/images/incontainer.png b/images/incontainer.png new file mode 100644 index 0000000..63d93db Binary files /dev/null and b/images/incontainer.png differ diff --git a/images/vstsSecurity.jpg b/images/vstsSecurity.jpg new file mode 100644 index 0000000..74c30e9 Binary files /dev/null and b/images/vstsSecurity.jpg differ diff --git a/images/vstsSecurity2.jpg b/images/vstsSecurity2.jpg new file mode 100644 index 0000000..225e1c9 Binary files /dev/null and b/images/vstsSecurity2.jpg differ