├── .gitattributes
├── .gitignore
├── .gitmodules
├── .nuget
├── NuGet.Config
├── NuGet.exe
└── NuGet.targets
├── Builder.Tests
├── Builder.Tests.csproj
├── DebuggerShim.cs
├── Features
│ └── StagerCanRunBuilderSpec.cs
├── Fixtures
│ ├── apps
│ │ ├── no-app
│ │ │ └── TextFile.txt
│ │ ├── run-procfile
│ │ │ ├── Procfile
│ │ │ └── custom.bat
│ │ └── run
│ │ │ └── run.bat
│ └── buildpacks
│ │ ├── nop-buildpack
│ │ └── bin
│ │ │ ├── compile.bat
│ │ │ ├── detect.bat
│ │ │ └── release.bat
│ │ └── run-buildpack
│ │ └── bin
│ │ ├── compile.bat
│ │ ├── detect.bat
│ │ └── release.bat
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Resources
│ └── bsdtar.exe
├── Specs
│ └── TarGZFileTest.cs
├── app.config
├── app
│ ├── Controllers
│ │ └── InstancesController.cs
│ ├── Global.asax
│ ├── Global.asax.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── README.md
│ ├── Web.Debug.config
│ ├── Web.Release.config
│ ├── Web.config
│ ├── favicon.ico
│ ├── nora.csproj
│ └── packages.config
└── packages.config
├── Builder
├── App.config
├── Builder.csproj
├── Options.cs
├── OutputMetadata.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Resources
│ └── bsdtar.exe
├── TarGZFile.cs
└── packages.config
├── LICENSE
├── Launcher.Tests
├── ArgumentEscaper.cs
├── DebuggerShim.cs
├── Features
│ └── LauncherCanRunStartCommandSpec.cs
├── Fixtures
│ ├── CivetCat.bat
│ └── Exit.bat
├── Launcher.Tests.csproj
├── Properties
│ └── AssemblyInfo.cs
├── Specs
│ └── IntegrationSpec.cs
└── packages.config
├── Launcher
├── App.config
├── Launcher.csproj
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── packages.config
├── NOTICE
├── README.md
├── Web.config
├── WebAppServer.Tests
├── DebuggerShim.cs
├── Features
│ └── WebAppServerHostsNetAppSpec.cs
├── Fixtures
│ ├── ASP-classic
│ │ ├── Web.config
│ │ └── default.asp
│ └── Nora
│ │ ├── Global.asax
│ │ ├── Web.config
│ │ ├── bin
│ │ ├── Newtonsoft.Json.dll
│ │ ├── Nora.dll
│ │ ├── System.Net.Http.Formatting.dll
│ │ ├── System.Web.Http.WebHost.dll
│ │ └── System.Web.Http.dll
│ │ └── packages.config
├── Properties
│ └── AssemblyInfo.cs
├── Specs
│ ├── OptionsTest.cs
│ ├── ProgramTest.cs
│ └── WebConfigTest.cs
├── Test.nunit
├── WebAppServer.Tests.csproj
├── app.config
└── packages.config
├── WebAppServer
├── ConfigGenerator.cs
├── Constants.cs
├── Logger.cs
├── Options.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Readme.txt
├── Resources
│ ├── applicationhost.config
│ ├── aspnet.config
│ └── v2.0AppHost.config
├── WebAppServer.csproj
├── WebConfig.cs
├── WebCoreActivationException.cs
├── WebServer.cs
└── XmlExtensions.cs
├── WindowsAppLifecycle.sln
├── appveyor.yml
├── bin
├── bsdtar.exe
└── nuget.exe
├── scripts
└── make.bat
└── vendor
├── CommandLineParser.1.9.71.nupkg
├── Newtonsoft.Json.8.0.3.nupkg
├── YamlDotNet.3.8.0.nupkg
└── nspec.0.9.68.nupkg
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | windows_app_lifecycle*.tgz
5 | diego-sshd.exe
6 |
7 | # User-specific files
8 | *.suo
9 | *.user
10 | *.sln.docstates
11 |
12 | # Build results
13 |
14 | [Dd]ebug/
15 | [Rr]elease/
16 | x64/
17 | build/
18 | [Bb]in/
19 | [Oo]bj/
20 |
21 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
22 | !packages/*/build/
23 |
24 | # MSTest test Results
25 | [Tt]est[Rr]esult*/
26 | [Bb]uild[Ll]og.*
27 |
28 | *_i.c
29 | *_p.c
30 | *.ilk
31 | *.meta
32 | *.obj
33 | *.pch
34 | *.pdb
35 | *.pgc
36 | *.pgd
37 | *.rsp
38 | *.sbr
39 | *.tlb
40 | *.tli
41 | *.tlh
42 | *.tmp
43 | *.tmp_proj
44 | *.log
45 | *.vspscc
46 | *.vssscc
47 | .builds
48 | *.pidb
49 | *.log
50 | *.scc
51 |
52 | # Visual C++ cache files
53 | ipch/
54 | *.aps
55 | *.ncb
56 | *.opensdf
57 | *.sdf
58 | *.cachefile
59 |
60 | # Visual Studio profiler
61 | *.psess
62 | *.vsp
63 | *.vspx
64 |
65 | # Guidance Automation Toolkit
66 | *.gpState
67 |
68 | # ReSharper is a .NET coding add-in
69 | _ReSharper*/
70 | *.[Rr]e[Ss]harper
71 |
72 | # TeamCity is a build add-in
73 | _TeamCity*
74 |
75 | # DotCover is a Code Coverage Tool
76 | *.dotCover
77 |
78 | # NCrunch
79 | *.ncrunch*
80 | .*crunch*.local.xml
81 |
82 | # Installshield output folder
83 | [Ee]xpress/
84 |
85 | # DocProject is a documentation generator add-in
86 | DocProject/buildhelp/
87 | DocProject/Help/*.HxT
88 | DocProject/Help/*.HxC
89 | DocProject/Help/*.hhc
90 | DocProject/Help/*.hhk
91 | DocProject/Help/*.hhp
92 | DocProject/Help/Html2
93 | DocProject/Help/html
94 |
95 | # Click-Once directory
96 | publish/
97 |
98 | # Publish Web Output
99 | *.Publish.xml
100 |
101 | # NuGet Packages Directory
102 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
103 | packages/
104 |
105 | # Windows Azure Build Output
106 | csx
107 | *.build.csdef
108 |
109 | # Windows Store app package directory
110 | AppPackages/
111 |
112 | # Others
113 | sql/
114 | *.Cache
115 | ClientBin/
116 | [Ss]tyle[Cc]op.*
117 | ~$*
118 | *~
119 | *.dbmdl
120 | *.[Pp]ublish.xml
121 | *.pfx
122 | *.publishsettings
123 |
124 | # RIA/Silverlight projects
125 | Generated_Code/
126 |
127 | # Backup & report files from converting an old project file to a newer
128 | # Visual Studio version. Backup files are not needed, because we have git ;-)
129 | _UpgradeReport_Files/
130 | Backup*/
131 | UpgradeLog*.XML
132 | UpgradeLog*.htm
133 |
134 | # SQL Server files
135 | App_Data/*.mdf
136 | App_Data/*.ldf
137 |
138 |
139 | #LightSwitch generated files
140 | GeneratedArtifacts/
141 | _Pvt_Extensions/
142 | ModelManifest.xml
143 |
144 | # =========================
145 | # Windows detritus
146 | # =========================
147 |
148 | # Windows image file caches
149 | Thumbs.db
150 | ehthumbs.db
151 |
152 | # Folder config file
153 | Desktop.ini
154 |
155 | # Recycle Bin used on file shares
156 | $RECYCLE.BIN/
157 |
158 | # Mac desktop service store files
159 | .DS_Store
160 |
161 |
162 | # Exception to fixtures
163 | !/Builder.Tests/Fixtures/**/*
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/.gitmodules
--------------------------------------------------------------------------------
/.nuget/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.nuget/NuGet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/.nuget/NuGet.exe
--------------------------------------------------------------------------------
/.nuget/NuGet.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildProjectDirectory)\..\
5 |
6 |
7 | false
8 |
9 |
10 | false
11 |
12 |
13 | true
14 |
15 |
16 | false
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
31 |
32 |
33 |
34 |
35 | $(SolutionDir).nuget
36 |
37 |
38 |
39 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config
40 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config
41 |
42 |
43 |
44 | $(MSBuildProjectDirectory)\packages.config
45 | $(PackagesProjectConfig)
46 |
47 |
48 |
49 |
50 | $(NuGetToolsPath)\NuGet.exe
51 | @(PackageSource)
52 |
53 | "$(NuGetExePath)"
54 | mono --runtime=v4.0.30319 "$(NuGetExePath)"
55 |
56 | $(TargetDir.Trim('\\'))
57 |
58 | -RequireConsent
59 | -NonInteractive
60 |
61 | "$(SolutionDir) "
62 | "$(SolutionDir)"
63 |
64 |
65 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)
66 | $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
67 |
68 |
69 |
70 | RestorePackages;
71 | $(BuildDependsOn);
72 |
73 |
74 |
75 |
76 | $(BuildDependsOn);
77 | BuildPackage;
78 |
79 |
80 |
81 |
82 |
83 |
84 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
99 |
100 |
103 |
104 |
105 |
106 |
108 |
109 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/Builder.Tests/Builder.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {2FE7925C-AC3E-4103-BF03-2D22F3D88610}
7 | Library
8 | Properties
9 | Builder.Tests
10 | BuilderTests
11 | v4.5
12 | 512
13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 10.0
15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
17 | False
18 | UnitTest
19 |
20 | ..\
21 | true
22 |
23 |
24 | true
25 | full
26 | false
27 | bin\Debug\
28 | DEBUG;TRACE
29 | prompt
30 | 4
31 |
32 |
33 | pdbonly
34 | true
35 | bin\Release\
36 | TRACE
37 | prompt
38 | 4
39 |
40 |
41 |
42 | ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll
43 | True
44 |
45 |
46 | ..\packages\nspec.0.9.68\lib\NSpec.dll
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | True
66 | True
67 | Resources.resx
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | PreserveNewest
76 |
77 |
78 | PreserveNewest
79 |
80 |
81 | PreserveNewest
82 |
83 |
84 | PreserveNewest
85 |
86 |
87 | PreserveNewest
88 |
89 |
90 | PreserveNewest
91 |
92 |
93 | PreserveNewest
94 |
95 |
96 | PreserveNewest
97 |
98 |
99 |
100 |
101 |
102 | {68f6a408-b0f2-4bb4-a0a4-278694fab63d}
103 | Builder
104 |
105 |
106 |
107 |
108 | ResXFileCodeGenerator
109 | Resources.Designer.cs
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | PreserveNewest
119 |
120 |
121 |
122 |
123 | PreserveNewest
124 |
125 |
126 |
127 |
128 |
129 |
130 | False
131 |
132 |
133 | False
134 |
135 |
136 | False
137 |
138 |
139 | False
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
150 |
151 |
152 |
153 |
160 |
--------------------------------------------------------------------------------
/Builder.Tests/DebuggerShim.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Reflection;
3 | using NSpec;
4 | using NSpec.Domain;
5 | using NSpec.Domain.Formatters;
6 |
7 | /*
8 | * Howdy,
9 | *
10 | * This is NSpec's DebuggerShim. It will allow you to use TestDriven.Net or Resharper's test runner to run
11 | * NSpec tests that are in the same Assembly as this class.
12 | *
13 | * It's DEFINITELY worth trying specwatchr (http://nspec.org/continuoustesting). Specwatchr automatically
14 | * runs tests for you.
15 | *
16 | * If you ever want to debug a test when using Specwatchr, simply put the following line in your test:
17 | *
18 | * System.Diagnostics.Debugger.Launch()
19 | *
20 | * Visual Studio will detect this and will give you a window which you can use to attach a debugger.
21 | */
22 |
23 | //[TestFixture]
24 | public class DebuggerShim
25 | {
26 | //[Test]
27 | public void debug()
28 | {
29 | var tagOrClassName = "class_or_tag_you_want_to_debug";
30 |
31 | var types = GetType().Assembly.GetTypes();
32 | // OR
33 | // var types = new Type[]{typeof(Some_Type_Containg_some_Specs)};
34 | var finder = new SpecFinder(types, "");
35 | var builder = new ContextBuilder(finder, new Tags().Parse(tagOrClassName), new DefaultConventions());
36 | var runner = new ContextRunner(builder, new ConsoleFormatter(), false);
37 | var results = runner.Run(builder.Contexts().Build());
38 |
39 | //assert that there aren't any failures
40 | results.Failures().Count().should_be(0);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Builder.Tests/Fixtures/apps/no-app/TextFile.txt:
--------------------------------------------------------------------------------
1 | dummy text
--------------------------------------------------------------------------------
/Builder.Tests/Fixtures/apps/run-procfile/Procfile:
--------------------------------------------------------------------------------
1 | web: custom.bat
--------------------------------------------------------------------------------
/Builder.Tests/Fixtures/apps/run-procfile/custom.bat:
--------------------------------------------------------------------------------
1 | echo App ran successfully. Exiting.
--------------------------------------------------------------------------------
/Builder.Tests/Fixtures/apps/run/run.bat:
--------------------------------------------------------------------------------
1 | echo App ran successfully. Exiting.
--------------------------------------------------------------------------------
/Builder.Tests/Fixtures/buildpacks/nop-buildpack/bin/compile.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | set build_path=%1
3 | set cache_path=%2
4 | :: do whatever is needed for the application to run
5 |
6 | echo Nothing to do ...
7 | echo Done.
8 |
9 | exit /b 0
10 |
--------------------------------------------------------------------------------
/Builder.Tests/Fixtures/buildpacks/nop-buildpack/bin/detect.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | set app_dir=%1
3 | :: detect if buildpack supports this application
4 |
5 | echo Nop Buildpack
6 | exit /b 0
--------------------------------------------------------------------------------
/Builder.Tests/Fixtures/buildpacks/nop-buildpack/bin/release.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | :: output valid yaml containing the start command
3 |
4 | echo ---
5 | echo default_process_types: []
6 |
--------------------------------------------------------------------------------
/Builder.Tests/Fixtures/buildpacks/run-buildpack/bin/compile.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | set build_path=%1
3 | set cache_path=%2
4 | :: do whatever is needed for the application to run
5 |
6 | echo Nothing to do ...
7 | echo No error 1>&2
8 | echo touch > %build_path%\compite-touch.txt
9 | echo touch > %cache_path%\compite-touch.txt
10 | echo Done.
11 |
12 | exit /b 0
13 |
--------------------------------------------------------------------------------
/Builder.Tests/Fixtures/buildpacks/run-buildpack/bin/detect.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | set app_dir=%1
3 | :: detect if buildpack supports this application
4 |
5 | if exist "%app_dir%\run.bat" (
6 | echo Run Buildpack
7 | exit /b 0
8 | ) else (
9 | exit /b 1
10 | )
11 |
--------------------------------------------------------------------------------
/Builder.Tests/Fixtures/buildpacks/run-buildpack/bin/release.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | :: output valid yaml containing the start command
3 |
4 | echo ---
5 | echo default_process_types:
6 | echo web: run.bat
7 |
--------------------------------------------------------------------------------
/Builder.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: AssemblyTitle("Builder.Tests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Builder.Tests")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("fa81399a-4b34-452b-8df4-e06a9f981cce")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Builder.Tests/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Builder.Tests.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Builder.Tests.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Byte[].
65 | ///
66 | internal static byte[] bsdtar {
67 | get {
68 | object obj = ResourceManager.GetObject("bsdtar", resourceCulture);
69 | return ((byte[])(obj));
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Builder.Tests/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\bsdtar.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
123 |
124 |
--------------------------------------------------------------------------------
/Builder.Tests/Resources/bsdtar.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/Builder.Tests/Resources/bsdtar.exe
--------------------------------------------------------------------------------
/Builder.Tests/Specs/TarGZFileTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Linq;
4 | using System.Reflection;
5 | using Builder.Tests.Properties;
6 | using NSpec;
7 | using System.IO;
8 |
9 | namespace Builder.Tests
10 | {
11 | class TarGZFileTest : nspec
12 | {
13 | string tgzPath, tmpDir, extractDir;
14 | private static string TarArchiverPath(string filename)
15 | {
16 | var uri = new Uri(Assembly.GetExecutingAssembly().CodeBase);
17 | return Path.Combine(Path.GetDirectoryName(uri.LocalPath), filename);
18 | }
19 |
20 | void before_all()
21 | {
22 | File.WriteAllBytes(TarArchiverPath("tar.exe"), Resources.bsdtar);
23 | }
24 |
25 | void before_each() {
26 | tgzPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
27 | tmpDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
28 | Directory.CreateDirectory(tmpDir);
29 | File.WriteAllText(Path.Combine(tmpDir, "a_file.txt"), "Some exciting text");
30 | Directory.CreateDirectory(Path.Combine(tmpDir, "a dir"));
31 | File.WriteAllText(Path.Combine(tmpDir, "a dir", "another_file.txt"), "Some spacey text");
32 | }
33 |
34 | void after_each()
35 | {
36 | Directory.Delete(tmpDir, true);
37 | if (Directory.Exists(extractDir))
38 | {
39 | Directory.Delete(extractDir, true);
40 | }
41 | if (File.Exists(tgzPath))
42 | {
43 | File.Delete(tgzPath);
44 | }
45 | }
46 |
47 | private void describe_CreateFromDirectory()
48 | {
49 | it["creates the tgz file"] = () =>
50 | {
51 | TarGZFile.CreateFromDirectory(tmpDir, tgzPath);
52 | File.Exists(tgzPath).should_be_true();
53 | };
54 |
55 | it["puts the files inside the file"] = () =>
56 | {
57 | TarGZFile.CreateFromDirectory(tmpDir, tgzPath);
58 |
59 | var process = new Process();
60 | var processStartInfo = process.StartInfo;
61 | processStartInfo.FileName = TarArchiverPath("tar.exe");
62 | processStartInfo.Arguments = "tf " + tgzPath;
63 | processStartInfo.RedirectStandardOutput = true;
64 | processStartInfo.UseShellExecute = false;
65 | process.Start();
66 | process.WaitForExit();
67 | var fileNames = process.StandardOutput.ReadToEnd();
68 | fileNames.should_contain(Path.GetFileName(tmpDir) + "/a_file.txt");
69 | fileNames.should_contain(Path.GetFileName(tmpDir) + "/a dir/another_file.txt");
70 | };
71 |
72 | it["can deal with Unicode in filenames"] = () =>
73 | {
74 | File.WriteAllText(Path.Combine(tmpDir, "新闻.txt"), "Chinese news");
75 | extractDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
76 | Directory.CreateDirectory(extractDir);
77 |
78 | TarGZFile.CreateFromDirectory(tmpDir, tgzPath);
79 |
80 | var process = new Process();
81 | var processStartInfo = process.StartInfo;
82 | processStartInfo.FileName = TarArchiverPath("tar.exe");
83 | processStartInfo.Arguments = "xf " + tgzPath + " -C " + extractDir;
84 | processStartInfo.UseShellExecute = false;
85 | process.Start();
86 | process.WaitForExit();
87 | var fileNames = Directory.EnumerateFiles(extractDir, "*", SearchOption.AllDirectories).ToList();
88 | fileNames.should_contain(Path.Combine(extractDir, Path.GetFileName(tmpDir)) + @"\新闻.txt");
89 | };
90 | }
91 | }
92 | }
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/Builder.Tests/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Builder.Tests/app/Controllers/InstancesController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Web.Http;
3 |
4 | namespace nora.Controllers
5 | {
6 | public class InstancesController : ApiController
7 | {
8 | [Route("~/")]
9 | [HttpGet]
10 | public IHttpActionResult Root()
11 | {
12 | return Ok("hello i am nora");
13 | }
14 |
15 | [Route("~/id")]
16 | [HttpGet]
17 | public IHttpActionResult Id()
18 | {
19 | const string uuid = "A123F285-26B4-45F1-8C31-816DC5F53ECF";
20 | return Ok(uuid);
21 | }
22 |
23 | [Route("~/env")]
24 | [HttpGet]
25 | public IHttpActionResult Env()
26 | {
27 | return Ok(Environment.GetEnvironmentVariables());
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Builder.Tests/app/Global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Codebehind="Global.asax.cs" Inherits="nora.WebApiApplication" Language="C#" %>
--------------------------------------------------------------------------------
/Builder.Tests/app/Global.asax.cs:
--------------------------------------------------------------------------------
1 | using System.Web;
2 | using System.Web.Http;
3 | using System.Web.Mvc;
4 | using System.Web.Optimization;
5 | using System.Web.Routing;
6 |
7 | namespace nora
8 | {
9 | public class WebApiApplication : HttpApplication
10 | {
11 | protected void Application_Start()
12 | {
13 | GlobalConfiguration.Configure((config) =>
14 | {
15 | // Web API configuration and services
16 |
17 | // Web API routes
18 | config.MapHttpAttributeRoutes();
19 |
20 | config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
21 | });
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/Builder.Tests/app/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 |
8 | [assembly: AssemblyTitle("nora")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("nora")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 |
21 | [assembly: ComVisible(false)]
22 |
23 | // The following GUID is for the ID of the typelib if this project is exposed to COM
24 |
25 | [assembly: Guid("12bf6eaf-ae7e-43cb-8363-b686f0afa644")]
26 |
27 | // Version information for an assembly consists of the following four values:
28 | //
29 | // Major Version
30 | // Minor Version
31 | // Build Number
32 | // Revision
33 | //
34 | // You can specify all the values or you can default the Revision and Build Numbers
35 | // by using the '*' as shown below:
36 |
37 | [assembly: AssemblyVersion("1.0.0.0")]
38 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/Builder.Tests/app/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Builder.Tests/app/Web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
29 |
30 |
--------------------------------------------------------------------------------
/Builder.Tests/app/Web.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/Builder.Tests/app/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/Builder.Tests/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/Builder.Tests/app/favicon.ico
--------------------------------------------------------------------------------
/Builder.Tests/app/nora.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 |
8 |
9 | 2.0
10 | {5FC9E271-52AB-4707-A3C1-23C7AB909ACA}
11 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
12 | Library
13 | Properties
14 | nora
15 | nora
16 | v4.5
17 | false
18 | true
19 |
20 |
21 |
22 |
23 |
24 |
25 | true
26 | full
27 | false
28 | bin\
29 | DEBUG;TRACE
30 | prompt
31 | 4
32 |
33 |
34 | pdbonly
35 | true
36 | bin\
37 | TRACE
38 | prompt
39 | 4
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll
52 |
53 |
54 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll
55 |
56 |
57 | ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.2\lib\net45\System.Web.Http.WebHost.dll
58 |
59 |
60 | True
61 | ..\packages\Microsoft.AspNet.Mvc.5.2.2\lib\net45\System.Web.Mvc.dll
62 |
63 |
64 | ..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll
65 |
66 |
67 |
68 |
69 | ..\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.dll
70 |
71 |
72 | ..\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.SqlServer.dll
73 |
74 |
75 | ..\packages\Microsoft.Owin.Security.OAuth.3.0.0\lib\net45\Microsoft.Owin.Security.OAuth.dll
76 |
77 |
78 | ..\packages\Microsoft.AspNet.WebApi.Owin.5.2.2\lib\net45\System.Web.Http.Owin.dll
79 |
80 |
81 |
82 |
83 |
84 | Global.asax
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | Web.config
94 |
95 |
96 | Web.config
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | 10.0
108 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | True
121 | True
122 | 57239
123 | /
124 | http://localhost:55408/
125 | False
126 | False
127 |
128 |
129 | False
130 |
131 |
132 |
133 |
134 |
140 |
--------------------------------------------------------------------------------
/Builder.Tests/app/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Builder.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Builder/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Builder/Builder.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {68F6A408-B0F2-4BB4-A0A4-278694FAB63D}
8 | Exe
9 | Properties
10 | Builder
11 | builder
12 | v4.5
13 | 512
14 |
15 | ..\
16 | true
17 | d326f9dd
18 |
19 |
20 | AnyCPU
21 | true
22 | full
23 | false
24 | bin\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 | false
29 |
30 |
31 | AnyCPU
32 | pdbonly
33 | true
34 | bin\
35 | TRACE
36 | prompt
37 | 4
38 | false
39 | false
40 |
41 |
42 |
43 | ..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll
44 |
45 |
46 | ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll
47 | True
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | ..\packages\YamlDotNet.3.8.0\lib\net35\YamlDotNet.dll
56 | True
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | True
66 | True
67 | Resources.resx
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | ResXFileCodeGenerator
78 | Resources.Designer.cs
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
89 |
90 |
91 |
92 |
99 |
--------------------------------------------------------------------------------
/Builder/Options.cs:
--------------------------------------------------------------------------------
1 | using CommandLine;
2 | using CommandLine.Text;
3 |
4 | namespace Builder
5 | {
6 | public enum OptionBool
7 | {
8 | False,
9 | True
10 | }
11 |
12 | public class Options
13 | {
14 | [Option("buildDir", Required = true)]
15 | public string BuildDir { get; set; }
16 |
17 | [Option("buildArtifactsCacheDir", Required = false)]
18 | public string BuildArtifactsCacheDir { get; set; }
19 |
20 | [Option("buildpackOrder", Required = false)]
21 | public string BuildpackOrder { get; set; }
22 |
23 | [Option("buildpacksDir", Required = false)]
24 | public string BuildpacksDir { get; set; }
25 |
26 | [Option("outputBuildArtifactsCache", Required = false)]
27 | public string OutputBuildArtifactsCache { get; set; }
28 |
29 | [Option("outputDroplet", Required = true)]
30 | public string OutputDroplet { get; set; }
31 |
32 | [Option("outputMetadata", Required = true)]
33 | public string OutputMetadata { get; set; }
34 |
35 | [Option("skipDetect", Required = false, DefaultValue = OptionBool.False)]
36 | public OptionBool SkipDetect { get; set; }
37 |
38 | [Option("skipCertVerify", Required = false)]
39 | public OptionBool SkipCertVerify { get; set; }
40 |
41 |
42 | [HelpOption]
43 | public string GetUsage()
44 | {
45 | return HelpText.AutoBuild(this,
46 | (HelpText current) => HelpText.DefaultParsingErrorsHandler(this, current));
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Builder/OutputMetadata.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Newtonsoft.Json;
3 | using YamlDotNet.Serialization;
4 | using System.Collections.Generic;
5 |
6 | namespace Builder
7 | {
8 | // Structure validation here:
9 | // https://github.com/cloudfoundry/cloud_controller_ng/blob/f418b7cc273a410b39938fc9a46d9d94f591d887/lib/cloud_controller/diego/buildpack/staging_completion_handler.rb#L11-L25
10 | public class OutputMetadata
11 | {
12 | [JsonProperty("lifecycle_type")]
13 | public string LifecycleType { get; set; }
14 |
15 | [JsonProperty("lifecycle_metadata")]
16 | public LifecycleMetadata LifecycleMetadata { get; set; }
17 |
18 | [JsonProperty("process_types")]
19 | public Dictionary ProcessTypes { get; set; }
20 |
21 | [JsonProperty("execution_metadata")]
22 | public string ExecutionMetadata { get; set; }
23 | }
24 |
25 | public class LifecycleMetadata
26 | {
27 | [JsonProperty("buildpack_key")]
28 | public string BuildpackKey { get; set; }
29 |
30 | [JsonProperty("detected_buildpack")]
31 | public string DetectedBuildpack { get; set; }
32 | }
33 |
34 | public class ReleaseInfo
35 | {
36 | [YamlMember(Alias = "default_process_types")]
37 | public Dictionary defaultProcessTypes { get; set; }
38 | }
39 | }
--------------------------------------------------------------------------------
/Builder/Program.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Globalization;
6 | using System.IO;
7 | using System.IO.Compression;
8 | using System.Linq;
9 | using System.Net;
10 | using System.Net.Security;
11 | using System.Security.Cryptography;
12 | using System.Text;
13 | using YamlDotNet.Serialization;
14 |
15 | namespace Builder
16 | {
17 | public class Program
18 | {
19 | private static string[] buildpackBinaries = new string[] { "detect", "compile", "release" };
20 |
21 | private static string[] binariesExtensions = new string[] { ".EXE", ".BAT", ".CMD" };
22 |
23 | private static bool IsWindowsBuildpack(string buildpackDir)
24 | {
25 | foreach (var app in buildpackBinaries)
26 | {
27 | bool found = false;
28 | foreach (string ext in binariesExtensions)
29 | {
30 | if (File.Exists(Path.Combine(buildpackDir, "bin", app + ext)))
31 | {
32 | found = true;
33 | }
34 | }
35 | if (!found)
36 | {
37 | return false;
38 | }
39 | }
40 | return true;
41 | }
42 |
43 | private static string GetExecutable(string path, string file)
44 | {
45 | foreach (string ext in binariesExtensions)
46 | {
47 | if (File.Exists(Path.Combine(path, file + ext)))
48 | {
49 | return Path.Combine(path, file + ext);
50 | }
51 | }
52 |
53 | throw new Exception(String.Format("No executable found for '{0}' in '{1}'", file, path));
54 | }
55 |
56 | private static int RunBuildpackProcess(string path, string args, TextWriter outputStream, TextWriter errorStream)
57 | {
58 | var p = new Process();
59 | p.StartInfo.FileName = path;
60 | p.StartInfo.Arguments = args;
61 | p.StartInfo.UseShellExecute = false;
62 | p.StartInfo.CreateNoWindow = true;
63 | p.StartInfo.RedirectStandardOutput = true;
64 | p.StartInfo.RedirectStandardError = true;
65 |
66 | p.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
67 | {
68 | outputStream.WriteLine(e.Data);
69 | };
70 | p.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
71 | {
72 | errorStream.WriteLine(e.Data);
73 | };
74 | p.Start();
75 | p.BeginOutputReadLine();
76 | p.BeginErrorReadLine();
77 | p.WaitForExit();
78 |
79 | return p.ExitCode;
80 | }
81 |
82 | private static string GetBuildpackDirName(string buildpackName)
83 | {
84 | using (MD5 md5Hash = MD5.Create())
85 | {
86 | byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(buildpackName));
87 | return BitConverter.ToString(data).Replace("-", "");
88 | }
89 | }
90 |
91 | private static void SanitizeArgs(string[] args)
92 | {
93 | for (int i = 0; i < args.Length; i++)
94 | {
95 | if (args[i].StartsWith("-") && !args[i].StartsWith("--"))
96 | {
97 | args[i] = "-" + args[i];
98 | }
99 | }
100 | }
101 |
102 | private static Dictionary GetProcfileProcessTypes(List files)
103 | {
104 | var procfiles = files.Where(x => Path.GetFileName(x).ToLower() == "procfile").ToList();
105 |
106 | if (procfiles.Any())
107 | {
108 | using (var procfileStream = new StreamReader(procfiles.First()))
109 | {
110 | return new Deserializer().Deserialize>(procfileStream);
111 | }
112 | }
113 | else
114 | {
115 | return null;
116 | }
117 | }
118 |
119 | private static void DownloadAndExtractZip(Uri source, string destination)
120 | {
121 | var tlsIgnoreFailureCallback = new RemoteCertificateValidationCallback(delegate { return true; });
122 | string tempFile = null;
123 |
124 | try
125 | {
126 | tempFile = Path.GetTempFileName();
127 |
128 | using (var webClient = new WebClient())
129 | {
130 | webClient.DownloadFile(source, tempFile);
131 | }
132 |
133 | ZipFile.ExtractToDirectory(tempFile, destination);
134 | }
135 | finally
136 | {
137 | if (tempFile != null)
138 | {
139 | File.Delete(tempFile);
140 | }
141 | }
142 | }
143 |
144 | private static bool IsZipBuildpack(string filename)
145 | {
146 | return filename.EndsWith(".zip", false, CultureInfo.InvariantCulture);
147 | }
148 |
149 | private static void DownloadBuildpacks(string[] buildpacks, string buildpacksDir)
150 | {
151 | foreach (var buildpackName in buildpacks)
152 | {
153 | Uri downloadUri = null;
154 | var downloadableBuildoack = Uri.TryCreate(buildpackName, UriKind.Absolute, out downloadUri);
155 | if (downloadableBuildoack)
156 | {
157 | var buildpackDir = Path.Combine(buildpacksDir, GetBuildpackDirName(buildpackName));
158 | if (IsZipBuildpack(buildpackName))
159 | {
160 | DownloadAndExtractZip(downloadUri, buildpackDir);
161 | }
162 | }
163 | }
164 | }
165 |
166 | static void Main(string[] args)
167 | {
168 | SanitizeArgs(args);
169 | var options = new Options();
170 | if (!CommandLine.Parser.Default.ParseArguments(args, options))
171 | {
172 | Environment.Exit(1);
173 | }
174 |
175 | Run(options);
176 | }
177 |
178 | private static void Run(Options options)
179 | {
180 | var rootDir = Directory.GetCurrentDirectory();
181 |
182 | var appPath = rootDir + options.BuildDir;
183 | var buildpacksDir = rootDir + options.BuildpacksDir;
184 |
185 | var buildCacheDir = rootDir + options.BuildArtifactsCacheDir;
186 | Directory.CreateDirectory(buildCacheDir);
187 |
188 | var outputCache = rootDir + options.OutputBuildArtifactsCache;
189 | var outputDropletPath = rootDir + options.OutputDroplet;
190 |
191 | string detectedBuildpack = "";
192 | string detectedBuildpackDir = "";
193 | string detectOutput = "";
194 | bool buildpackDetected = false;
195 |
196 | var buildpacks = new string[0];
197 | if (options.BuildpackOrder != null)
198 | {
199 | buildpacks = options.BuildpackOrder.Split(new char[] { ',' });
200 | }
201 |
202 | DownloadBuildpacks(buildpacks, buildpacksDir);
203 |
204 | foreach (var buildpackName in buildpacks)
205 | {
206 | var buildpackDir = Path.Combine(buildpacksDir, GetBuildpackDirName(buildpackName));
207 |
208 | if (!IsWindowsBuildpack(buildpackDir))
209 | {
210 | continue;
211 | }
212 |
213 | if (options.SkipDetect == OptionBool.False)
214 | {
215 | var detectPath = GetExecutable(Path.Combine(buildpackDir, "bin"), "detect");
216 |
217 | var outputStream = new StringWriter();
218 | var exitCode = RunBuildpackProcess(detectPath, appPath, outputStream, Console.Error);
219 | detectOutput = outputStream.ToString();
220 |
221 | detectOutput = detectOutput.TrimEnd(new char[] { '\n', '\r' });
222 |
223 | if (exitCode == 0)
224 | {
225 | detectedBuildpack = buildpackName;
226 | detectedBuildpackDir = buildpackDir;
227 | buildpackDetected = true;
228 | break;
229 | }
230 | }
231 | else
232 | {
233 | detectedBuildpack = buildpackName;
234 | detectedBuildpackDir = buildpackDir;
235 | buildpackDetected = true;
236 | break;
237 | }
238 | }
239 |
240 | if (!buildpackDetected)
241 | {
242 | Console.WriteLine("None of the buildpacks detected a compatible application");
243 | Environment.Exit(222);
244 | }
245 |
246 | var compilePath = GetExecutable(Path.Combine(detectedBuildpackDir, "bin"), "compile");
247 |
248 | var compoileExitCode = RunBuildpackProcess(compilePath, appPath + " " + buildCacheDir, Console.Out, Console.Error);
249 | if (compoileExitCode != 0)
250 | {
251 | Console.WriteLine("Failed to compile droplet");
252 | Environment.Exit(223);
253 | }
254 |
255 | Dictionary procfileProcessTypes = GetProcfileProcessTypes(Directory.EnumerateFiles(appPath).ToList());
256 |
257 | var releaseBinPath = GetExecutable(Path.Combine(detectedBuildpackDir, "bin"), "release");
258 |
259 | var releaseStream = new StringWriter();
260 | var releaseExitCode = RunBuildpackProcess(releaseBinPath, appPath, releaseStream, Console.Error);
261 | if (releaseExitCode != 0)
262 | {
263 | Console.WriteLine("Failed to build droplet release");
264 | Environment.Exit(224);
265 | }
266 |
267 | var releaseOutput = releaseStream.ToString();
268 | ReleaseInfo releaseInfo = new Deserializer(ignoreUnmatched: true).Deserialize(new StringReader(releaseOutput));
269 |
270 | var outputMetadata = new OutputMetadata()
271 | {
272 | LifecycleType = "buildpack",
273 | LifecycleMetadata = new LifecycleMetadata()
274 | {
275 | BuildpackKey = detectedBuildpack,
276 | DetectedBuildpack = detectOutput
277 | },
278 | ProcessTypes = procfileProcessTypes ?? releaseInfo.defaultProcessTypes,
279 | ExecutionMetadata = ""
280 | };
281 |
282 | File.WriteAllText(rootDir + options.OutputMetadata, JsonConvert.SerializeObject(outputMetadata));
283 |
284 | TarGZFile.CreateFromDirectory(buildCacheDir + "\\", outputCache);
285 | TarGZFile.CreateFromDirectory(appPath, outputDropletPath);
286 | }
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/Builder/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: AssemblyTitle("Builder")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Builder")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("a99915a0-03f9-4346-86fb-5164fe025038")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Builder/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Builder.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Builder.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Byte[].
65 | ///
66 | internal static byte[] bsdtar {
67 | get {
68 | object obj = ResourceManager.GetObject("bsdtar", resourceCulture);
69 | return ((byte[])(obj));
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Builder/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\bsdtar.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
123 |
124 |
--------------------------------------------------------------------------------
/Builder/Resources/bsdtar.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/Builder/Resources/bsdtar.exe
--------------------------------------------------------------------------------
/Builder/TarGZFile.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Reflection;
6 | using Builder.Properties;
7 |
8 | namespace Builder
9 | {
10 | public class TarGZFile
11 | {
12 | private static string TarArchiverPath(string filename)
13 | {
14 | var uri = new Uri(Assembly.GetExecutingAssembly().CodeBase);
15 | return Path.Combine(Path.GetDirectoryName(uri.LocalPath), filename);
16 | }
17 |
18 | static TarGZFile()
19 | {
20 | File.WriteAllBytes(TarArchiverPath("tar.exe"), Resources.bsdtar);
21 | }
22 |
23 | public static void CreateFromDirectory(string fullSourcePath, string destinationArchiveFileName)
24 | {
25 | var parentPath = Path.GetDirectoryName(fullSourcePath);
26 | var baseName = Path.GetFileName(fullSourcePath);
27 | if (string.IsNullOrEmpty(baseName))
28 | {
29 | baseName = ".";
30 | }
31 |
32 | var process = new Process();
33 | var processStartInfo = process.StartInfo;
34 | processStartInfo.FileName = TarArchiverPath("tar.exe");
35 | processStartInfo.Arguments = "czf " + destinationArchiveFileName + " -C " + parentPath + " " + baseName;
36 | processStartInfo.UseShellExecute = false;
37 | process.Start();
38 | process.WaitForExit();
39 | var exitCode = process.ExitCode;
40 | if (exitCode != 0)
41 | {
42 | throw new Exception("Failed to create archive");
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Builder/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/Launcher.Tests/ArgumentEscaper.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 |
3 | namespace Launcher
4 | {
5 | public static class ArgumentEscaper
6 | {
7 | public static string Escape(string[] args)
8 | {
9 | var builder = new StringBuilder();
10 | foreach (string arg in args)
11 | {
12 | if (builder.Length > 0)
13 | builder.Append(" ");
14 |
15 | builder.Append("\"")
16 | .Append(arg.Replace("\\", "\\\\").Replace("\"", "\\\""))
17 | .Append("\"");
18 | }
19 | return builder.ToString();
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Launcher.Tests/DebuggerShim.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Reflection;
3 | using NSpec;
4 | using NSpec.Domain;
5 | using NSpec.Domain.Formatters;
6 |
7 | /*
8 | * Howdy,
9 | *
10 | * This is NSpec's DebuggerShim. It will allow you to use TestDriven.Net or Resharper's test runner to run
11 | * NSpec tests that are in the same Assembly as this class.
12 | *
13 | * It's DEFINITELY worth trying specwatchr (http://nspec.org/continuoustesting). Specwatchr automatically
14 | * runs tests for you.
15 | *
16 | * If you ever want to debug a test when using Specwatchr, simply put the following line in your test:
17 | *
18 | * System.Diagnostics.Debugger.Launch()
19 | *
20 | * Visual Studio will detect this and will give you a window which you can use to attach a debugger.
21 | */
22 |
23 | //[TestFixture]
24 | public class DebuggerShim
25 | {
26 | //[Test]
27 | public void debug()
28 | {
29 | var tagOrClassName = "class_or_tag_you_want_to_debug";
30 |
31 | var types = GetType().Assembly.GetTypes();
32 | // OR
33 | // var types = new Type[]{typeof(Some_Type_Containg_some_Specs)};
34 | var finder = new SpecFinder(types, "");
35 | var builder = new ContextBuilder(finder, new Tags().Parse(tagOrClassName), new DefaultConventions());
36 | var runner = new ContextRunner(builder, new ConsoleFormatter(), false);
37 | var results = runner.Run(builder.Contexts().Build());
38 |
39 | //assert that there aren't any failures
40 | results.Failures().Count().should_be(0);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Launcher.Tests/Features/LauncherCanRunStartCommandSpec.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.IO;
3 | using NSpec;
4 | using System;
5 |
6 | namespace Launcher.Tests.Features
7 | {
8 | internal class LauncherCanRunStartCommandSpec : nspec
9 | {
10 | private Process StartLauncher(params string[] args)
11 | {
12 | var startInfo = new ProcessStartInfo
13 | {
14 | Arguments = ArgumentEscaper.Escape(args),
15 | FileName = "Launcher.exe",
16 | RedirectStandardError = true,
17 | RedirectStandardOutput = true,
18 | UseShellExecute = false
19 | };
20 | var proc = Process.Start(startInfo);
21 | proc.should_not_be_null();
22 | proc.WaitForExit();
23 | return proc;
24 | }
25 |
26 | private void describe_()
27 | {
28 | before = () =>
29 | {
30 | var workingDirectory = Path.GetFullPath(Path.Combine(System.Reflection.Assembly.GetExecutingAssembly().CodeBase, "..").Replace("file:///", ""));
31 | Directory.SetCurrentDirectory(workingDirectory);
32 | };
33 |
34 | after = () => File.Delete(@"Fixtures\Bean.txt");
35 |
36 | describe["when started with insufficient arguments"] = () =>
37 | {
38 |
39 | it["outputs a message onto STDERR"] = () =>
40 | {
41 | var launcher = StartLauncher();
42 | launcher.StandardError.ReadToEnd().should_contain("Launcher was run with insufficient arguments");
43 | };
44 |
45 | it["returns an exit code of 1"] = () =>
46 | {
47 | var launcher = StartLauncher();
48 | launcher.ExitCode.should_be(1);
49 | };
50 | };
51 |
52 |
53 | describe["when a start command is provided to the Launcher"] = () =>
54 | {
55 | it["runs it"] = () =>
56 | {
57 | StartLauncher("Fixtures", "CivetCat.bat bean1 bean2");
58 |
59 | var beans = File.ReadAllText(@"Fixtures\Bean.txt").Split('\n');
60 | beans[0].should_contain("bean1");
61 | beans[1].should_contain("bean2");
62 | };
63 |
64 | it["returns the exit code from it"] = () =>
65 | {
66 | var launcher = StartLauncher("Fixtures", @"CivetCat.bat");
67 | launcher.ExitCode.should_be(0);
68 |
69 | launcher = StartLauncher("Fixtures", "Exit.bat 5678");
70 | launcher.ExitCode.should_be(5678);
71 | };
72 |
73 | it["propagates stdout from it"] = () =>
74 | {
75 | var launcher = StartLauncher("Fixtures", "CivetCat.bat");
76 | var stdout = launcher.StandardOutput.ReadToEnd();
77 | stdout.should_contain("This is STDOUT");
78 | };
79 |
80 | it["propagates stderr from it"] = () =>
81 | {
82 | var launcher = StartLauncher("Fixtures", "CivetCat.bat");
83 | var stderr = launcher.StandardError.ReadToEnd();
84 | stderr.should_contain("This is STDERR");
85 | };
86 |
87 | it["properly splits up arguments"] = () =>
88 | {
89 | StartLauncher("Fixtures", "CivetCat.bat bean1 bean2");
90 |
91 | var beans = File.ReadAllText(@"Fixtures\Bean.txt").Split('\n');
92 | beans[0].should_contain("bean1");
93 | beans[1].should_contain("bean2");
94 |
95 | StartLauncher("Fixtures", "CivetCat.bat \"bean1 bean2\"");
96 |
97 | var beans2 = File.ReadAllText(@"Fixtures\Bean.txt").Split('\n');
98 | beans2[0].should_contain("bean1 bean2");
99 | };
100 |
101 | it["works with absolute paths with quoted arguments"] = () =>
102 | {
103 | StartLauncher("Fixtures", "/Fixtures/CivetCat.bat \"bean1\" \"bean2\"");
104 |
105 | var beans = File.ReadAllText(@"Fixtures\Bean.txt").Split('\n');
106 | beans[0].should_contain("bean1");
107 | beans[1].should_contain("bean2");
108 | };
109 | };
110 | }
111 | }
112 | }
--------------------------------------------------------------------------------
/Launcher.Tests/Fixtures/CivetCat.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal enabledelayedexpansion
3 |
4 | del Bean.txt
5 |
6 | set argCount=0
7 | for %%x in (%*) do (
8 | set /A argCount+=1
9 | set "argVec[!argCount!]=%%~x"
10 | )
11 |
12 | for /L %%i in (1,1,%argCount%) do (
13 | echo "!argVec[%%i]!" >> Bean.txt
14 | )
15 |
16 | echo This is STDOUT
17 | echo This is STDERR >&2
18 |
--------------------------------------------------------------------------------
/Launcher.Tests/Fixtures/Exit.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | exit /b %*
--------------------------------------------------------------------------------
/Launcher.Tests/Launcher.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {273733E4-6283-4E52-9CED-10EFA609EB38}
8 | Library
9 | Properties
10 | Launcher.Tests
11 | LauncherTests
12 | v4.5
13 | 512
14 |
15 | ..\
16 | true
17 |
18 |
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 | ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll
38 | True
39 |
40 |
41 | ..\packages\nspec.0.9.68\lib\NSpec.dll
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | PreserveNewest
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | {956F7FAD-B936-4ED7-9685-4D963E4CBDD6}
65 | Launcher
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
74 |
75 |
76 |
77 |
84 |
--------------------------------------------------------------------------------
/Launcher.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: AssemblyTitle("Launcher.Tests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Launcher.Tests")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("87cd9680-2817-4908-ab37-09b02e4b6f1f")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Launcher.Tests/Specs/IntegrationSpec.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Reflection;
6 | using Newtonsoft.Json;
7 | using NSpec;
8 |
9 | namespace Launcher.Tests.Specs
10 | {
11 | class IntegrationSpec : nspec
12 | {
13 | public static string AssemblyDirectory
14 | {
15 | get
16 | {
17 | string codeBase = Assembly.GetExecutingAssembly().CodeBase;
18 | UriBuilder uri = new UriBuilder(codeBase);
19 | string path = Uri.UnescapeDataString(uri.Path);
20 | return Path.GetDirectoryName(path);
21 | }
22 | }
23 |
24 | public void describe_()
25 | {
26 | describe["an app started with no start command"] = () =>
27 | {
28 | it["prints an error message"] = () =>
29 | {
30 | var startInfo = new ProcessStartInfo(AssemblyDirectory + @"\..\..\..\Launcher\bin\Launcher.exe")
31 | {
32 | Arguments = "\"\" \"\"",
33 | UseShellExecute = false,
34 | RedirectStandardError = true,
35 | RedirectStandardOutput = true,
36 |
37 | };
38 |
39 | var process = Process.Start(startInfo);
40 | process.WaitForExit(1000);
41 | var stderr = process.StandardError.ReadToEnd();
42 | stderr.should_contain("Could not determine a start command");
43 | process.ExitCode.should_be(1);
44 | };
45 | };
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Launcher.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Launcher/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Launcher/Launcher.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {956F7FAD-B936-4ED7-9685-4D963E4CBDD6}
8 | Exe
9 | Properties
10 | Launcher
11 | launcher
12 | v4.5
13 | 512
14 |
15 | ..\
16 | true
17 | publish\
18 | true
19 | Disk
20 | false
21 | Foreground
22 | 7
23 | Days
24 | false
25 | false
26 | true
27 | 0
28 | 1.0.0.%2a
29 | false
30 | false
31 | true
32 |
33 |
34 | AnyCPU
35 | true
36 | full
37 | false
38 | bin\
39 | DEBUG;TRACE
40 | prompt
41 | 4
42 | false
43 |
44 |
45 | AnyCPU
46 | pdbonly
47 | true
48 | bin\
49 | TRACE
50 | prompt
51 | 4
52 | false
53 | false
54 |
55 |
56 |
57 | ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll
58 | True
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | False
74 | .NET Framework 3.5 SP1 Client Profile
75 | false
76 |
77 |
78 | False
79 | .NET Framework 3.5 SP1
80 | false
81 |
82 |
83 |
84 |
85 |
86 |
87 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
88 |
89 |
90 |
91 |
98 |
--------------------------------------------------------------------------------
/Launcher/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Runtime.InteropServices;
5 | using System.Threading;
6 | using Newtonsoft.Json;
7 |
8 | namespace Launcher
9 | {
10 | public class ExecutionMetadata
11 | {
12 | [JsonProperty("start_command")]
13 | public string StartCommand { get; set; }
14 |
15 | [JsonProperty("start_command_args")]
16 | public string[] StartCommandArgs { get; set; }
17 | }
18 |
19 | internal class Program
20 | {
21 | private static int Main(string[] args)
22 | {
23 | if (args.Length < 2)
24 | {
25 | Console.Error.WriteLine("Launcher was run with insufficient arguments. Usage: launcher.exe ");
26 | return 1;
27 | }
28 |
29 | var containerRoot = Directory.GetCurrentDirectory();
30 | var workingDirectory = Path.Combine(containerRoot, args[0]);
31 | var executablePathAndArgs = args[1];
32 |
33 | if (String.IsNullOrWhiteSpace(executablePathAndArgs))
34 | {
35 | Console.Error.WriteLine("Could not determine a start command. Use the -c flag to 'cf push' to specify a custom start command.");
36 | return 1;
37 | }
38 | if (executablePathAndArgs[0] == '/')
39 | {
40 | executablePathAndArgs = containerRoot + executablePathAndArgs;
41 | }
42 | Console.Out.WriteLine("Running {0}", executablePathAndArgs);
43 |
44 | Directory.SetCurrentDirectory(workingDirectory);
45 | return StartProcess(executablePathAndArgs);
46 | }
47 |
48 | private static int StartProcess(string executablePathAndArgs)
49 | {
50 | STARTUPINFO startupInformation = new STARTUPINFO();
51 | PROCESS_INFORMATION processInformation;
52 | var result = CreateProcess(null, executablePathAndArgs, IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref startupInformation, out processInformation);
53 | if (!result)
54 | {
55 | var errorCode = Marshal.GetLastWin32Error();
56 | Console.Error.WriteLine(new System.ComponentModel.Win32Exception(errorCode).Message);
57 | return errorCode;
58 | }
59 | WaitForSingleObject(processInformation.hProcess, INFINITE);
60 | UInt32 exitCode = 0;
61 | GetExitCodeProcess(processInformation.hProcess, ref exitCode);
62 | return (int) exitCode;
63 | }
64 |
65 | [DllImport("kernel32.dll", SetLastError = true)]
66 | static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes,
67 | IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags,
68 | IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo,
69 | out PROCESS_INFORMATION lpProcessInformation);
70 |
71 | [DllImport("kernel32.dll", SetLastError = true)]
72 | static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
73 |
74 | [DllImport("kernel32.dll", SetLastError = true)]
75 | public static extern bool GetExitCodeProcess(IntPtr process, ref UInt32 exitCode);
76 |
77 | const UInt32 INFINITE = 0xFFFFFFFF;
78 | }
79 |
80 | public struct PROCESS_INFORMATION
81 | {
82 | public IntPtr hProcess;
83 | public IntPtr hThread;
84 | public uint dwProcessId;
85 | public uint dwThreadId;
86 | }
87 |
88 | public struct STARTUPINFO
89 | {
90 | public uint cb;
91 | public string lpReserved;
92 | public string lpDesktop;
93 | public string lpTitle;
94 | public uint dwX;
95 | public uint dwY;
96 | public uint dwXSize;
97 | public uint dwYSize;
98 | public uint dwXCountChars;
99 | public uint dwYCountChars;
100 | public uint dwFillAttribute;
101 | public uint dwFlags;
102 | public short wShowWindow;
103 | public short cbReserved2;
104 | public IntPtr lpReserved2;
105 | public IntPtr hStdInput;
106 | public IntPtr hStdOutput;
107 | public IntPtr hStdError;
108 | }
109 |
110 | public struct SECURITY_ATTRIBUTES
111 | {
112 | public int length;
113 | public IntPtr lpSecurityDescriptor;
114 | public bool bInheritHandle;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/Launcher/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: AssemblyTitle("Launcher")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Launcher")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("20debaf7-4659-4d06-82d4-0222d04b930d")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Launcher/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014-2015 Pivotal Software, Inc. All Rights Reserved.
2 |
3 | This product is licensed to you under the Apache License, Version 2.0 (the "License").
4 | You may not use this product except in compliance with the License.
5 |
6 | This product may include a number of subcomponents with separate copyright notices
7 | and license terms. Your use of these subcomponents is subject to the terms and
8 | conditions of the subcomponent's license, as noted in the LICENSE file.
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | windows app lifecycle
2 | =====================
3 |
4 | The windows application lifecycle implements the traditional Cloud Foundry deployment
5 | strategy.
6 |
7 | The **Builder** downloads buildpacks and app bits, and produces a droplet.
8 |
9 | The **Launcher** runs the start command using a standard rootfs and
10 | environment.
11 |
12 | The **WebAppServer** runs a HostableWebCore server to host the user's app.
13 |
14 | Read about the app lifecycle spec here: https://github.com/cloudfoundry-incubator/diego-design-notes#app-lifecycles
15 |
16 | ## Dependencies
17 | - 64 bit version of Windows (tested with Windows Server 2012 R2 Standard)
18 | - msbuild in PATH
19 | - Administrator access
20 |
21 | building on the command line
22 | ============================
23 |
24 | 1. Run make.bat in cmd.
25 |
26 | building in Visual Studio
27 | ========================
28 |
29 | 1. Install https://visualstudiogallery.msdn.microsoft.com/7a52473f-9e1a-40f3-8bd8-6c00ab163609 (nspec test runner)
30 |
31 | 1. Open Visual Studio as Administrator.
32 | 
33 | 
34 |
--------------------------------------------------------------------------------
/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/DebuggerShim.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Reflection;
3 | using NSpec;
4 | using NSpec.Domain;
5 | using NSpec.Domain.Formatters;
6 |
7 | /*
8 | * Howdy,
9 | *
10 | * This is NSpec's DebuggerShim. It will allow you to use TestDriven.Net or Resharper's test runner to run
11 | * NSpec tests that are in the same Assembly as this class.
12 | *
13 | * It's DEFINITELY worth trying specwatchr (http://nspec.org/continuoustesting). Specwatchr automatically
14 | * runs tests for you.
15 | *
16 | * If you ever want to debug a test when using Specwatchr, simply put the following line in your test:
17 | *
18 | * System.Diagnostics.Debugger.Launch()
19 | *
20 | * Visual Studio will detect this and will give you a window which you can use to attach a debugger.
21 | */
22 |
23 | //[TestFixture]
24 | public class DebuggerShim
25 | {
26 | //[Test]
27 | public void debug()
28 | {
29 | var tagOrClassName = "class_or_tag_you_want_to_debug";
30 |
31 | var types = GetType().Assembly.GetTypes();
32 | // OR
33 | // var types = new Type[]{typeof(Some_Type_Containg_some_Specs)};
34 | var finder = new SpecFinder(types, "");
35 | var builder = new ContextBuilder(finder, new Tags().Parse(tagOrClassName), new DefaultConventions());
36 | var runner = new ContextRunner(builder, new ConsoleFormatter(), false);
37 | var results = runner.Run(builder.Contexts().Build());
38 |
39 | //assert that there aren't any failures
40 | results.Failures().Count().should_be(0);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/Features/WebAppServerHostsNetAppSpec.cs:
--------------------------------------------------------------------------------
1 | using NSpec;
2 | using System;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Net;
6 | using System.Net.Http;
7 | using System.Security.Principal;
8 | using System.Threading;
9 | using System.Linq;
10 |
11 | namespace WebAppServer.Tests
12 | {
13 | class WebAppServerHostsNetAppSpec : nspec
14 | {
15 | const string processName = "WebAppServer.exe";
16 | const int port = 43311;
17 | private void describe_()
18 | {
19 | Process process = null;
20 |
21 | before = () =>
22 | {
23 | KillOrphanWebAppServer();
24 | };
25 |
26 | after = () =>
27 | {
28 | if (!process.HasExited)
29 | {
30 | process.Kill();
31 | process.WaitForExit();
32 | }
33 |
34 | if (process.ExitCode == 1)
35 | {
36 | throw new Exception(
37 | String.Format(
38 | "WebAppServer failed to start. Check that the current user has access to the port (eg. run 'netsh http add urlacl url=http://*:{0}/ user={1}' as an Administrator).",
39 | port,
40 | WindowsIdentity.GetCurrent().Name));
41 | }
42 | };
43 |
44 | describe["Given that I have a ASP.NET MVC application"] = () =>
45 | {
46 | describe["When I pass it to WebAppServer"] = () =>
47 | {
48 |
49 | act = () =>
50 | {
51 | process = StartApp("Nora");
52 | };
53 |
54 | it["runs it on the specified port"] = () =>
55 | {
56 | var client = new HttpClient();
57 | var response = client.GetAsync("http://localhost:" + port).GetAwaiter().GetResult();
58 | response.StatusCode.should_be(HttpStatusCode.OK);
59 | response.Content.ReadAsStringAsync().Result.should_be("\"hello i am nora\"");
60 | };
61 |
62 | it["does not add unexpected custom headers"] = () =>
63 | {
64 | var client = new HttpClient();
65 | var response = client.GetAsync("http://localhost:" + port).GetAwaiter().GetResult();
66 | response.StatusCode.should_be(HttpStatusCode.OK);
67 |
68 | var CustomHeaders = response.Headers.Where((x) => x.Key.StartsWith("X-")).Select((x) => x.Key).ToList();
69 | CustomHeaders.should_be(new string[] { "X-AspNet-Version" });
70 | };
71 |
72 | };
73 | };
74 |
75 | describe["Given that I have a ASP classic application"] = () =>
76 | {
77 | it["runs it on the specified port"] = () =>
78 | {
79 | var client = new HttpClient();
80 | var response = client.GetAsync("http://localhost:" + port).GetAwaiter().GetResult();
81 | response.StatusCode.should_be(HttpStatusCode.OK);
82 | response.Content.ReadAsStringAsync().Result.should_be("Hello World!");
83 | };
84 |
85 | act = () =>
86 | {
87 | process = StartApp("ASP-classic");
88 | };
89 | };
90 | }
91 |
92 | private Process StartApp(string fixtureName)
93 | {
94 | Process process;
95 | var workingDir =
96 | Path.GetFullPath(
97 | Path.Combine(System.Reflection.Assembly.GetExecutingAssembly().CodeBase, "..", "..", "..")
98 | .Replace("file:///", ""));
99 | var webRoot = Path.Combine(workingDir, "Fixtures", fixtureName);
100 |
101 | process = new Process
102 | {
103 | StartInfo =
104 | {
105 | FileName = Path.Combine(workingDir, "..", "WebAppServer", "bin", processName),
106 | Arguments = ".",
107 | WorkingDirectory = webRoot,
108 | RedirectStandardInput = true,
109 | RedirectStandardError = true,
110 | RedirectStandardOutput = true,
111 | UseShellExecute = false
112 | }
113 | };
114 | process.StartInfo.EnvironmentVariables["PORT"] = port.ToString();
115 |
116 | process.Start();
117 |
118 | // wait for the web app server to start to avoid race conditions
119 | while (!process.HasExited)
120 | {
121 | var readLine = process.StandardOutput.ReadLine();
122 | readLine.should_not_be_null();
123 | if (readLine.Contains("Server Started"))
124 | {
125 | break;
126 | }
127 | }
128 | return process;
129 | }
130 |
131 | private void KillOrphanWebAppServer()
132 | {
133 | const string force = "/f";
134 | const string alsoKillChildProcesses = "/t";
135 | const string useProcessName = "/im";
136 | var killOrphanProcess = new Process
137 | {
138 | StartInfo =
139 | {
140 | FileName = "taskkill.exe",
141 | Arguments =
142 | String.Format("{0} {1} {2} {3}", force, alsoKillChildProcesses, useProcessName,
143 | processName),
144 | UseShellExecute = false,
145 | RedirectStandardError = true
146 | }
147 | };
148 |
149 | killOrphanProcess.Start();
150 | var stderr = killOrphanProcess.StandardError.ReadToEnd();
151 | if (stderr.Contains("Access is denied"))
152 | {
153 | throw new Exception(String.Format("Could not remove orphan {0}." +
154 | "This is likely because WinowsAppLifecycle was previously run as Administrator," +
155 | " and is currently running under a non privleged user. To fix:" +
156 | " run \"taskkill.exe /f /t /im {0}\" in admin command prompt", processName));
157 |
158 | }
159 | killOrphanProcess.WaitForExit();
160 | }
161 | }
162 | }
163 |
164 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/Fixtures/ASP-classic/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/Fixtures/ASP-classic/default.asp:
--------------------------------------------------------------------------------
1 | <%
2 | response.write("Hello World!")
3 | %>
4 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/Fixtures/Nora/Global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Nora.WebApiApplication" Language="C#" %>
2 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/Fixtures/Nora/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/Fixtures/Nora/bin/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/WebAppServer.Tests/Fixtures/Nora/bin/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/WebAppServer.Tests/Fixtures/Nora/bin/Nora.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/WebAppServer.Tests/Fixtures/Nora/bin/Nora.dll
--------------------------------------------------------------------------------
/WebAppServer.Tests/Fixtures/Nora/bin/System.Net.Http.Formatting.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/WebAppServer.Tests/Fixtures/Nora/bin/System.Net.Http.Formatting.dll
--------------------------------------------------------------------------------
/WebAppServer.Tests/Fixtures/Nora/bin/System.Web.Http.WebHost.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/WebAppServer.Tests/Fixtures/Nora/bin/System.Web.Http.WebHost.dll
--------------------------------------------------------------------------------
/WebAppServer.Tests/Fixtures/Nora/bin/System.Web.Http.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/WebAppServer.Tests/Fixtures/Nora/bin/System.Web.Http.dll
--------------------------------------------------------------------------------
/WebAppServer.Tests/Fixtures/Nora/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/WebAppServer.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: AssemblyTitle("WebAppServer.Tests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("WebAppServer.Tests")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("cfb9c5fb-5ba7-4daf-a511-d784a88148a1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/Specs/OptionsTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using NSpec;
8 |
9 | namespace WebAppServer.Tests.Specs
10 | {
11 | class OptionsTest : nspec
12 | {
13 | private void describe_()
14 | {
15 | describe["Parse"] = () =>
16 | {
17 | Options options = null;
18 | string path = null;
19 | string port = null;
20 |
21 | before = () =>
22 | {
23 | port = "9999";
24 | Environment.SetEnvironmentVariable("PORT", port);
25 | options = new Options();
26 | };
27 |
28 | act = () =>
29 | {
30 | options.Parse(new string[] { });
31 | };
32 |
33 | it["parses port as an int"] = () =>
34 | {
35 | options.Port.should_be(9999U);
36 | };
37 |
38 |
39 | it["returns the full path to the current directory"] = () =>
40 | {
41 | options.WebRoot.should_be(Directory.GetCurrentDirectory());
42 | };
43 | };
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/Specs/ProgramTest.cs:
--------------------------------------------------------------------------------
1 | using Moq;
2 | using NSpec;
3 | using System.Threading;
4 |
5 | namespace WebAppServer.Tests.Specs
6 | {
7 | class ProgramTest : nspec
8 | {
9 | void describe_()
10 | {
11 | describe["RunWebServer"] = () =>
12 | {
13 | Mock webServer = null;
14 | Mock log = null;
15 |
16 | before = () =>
17 | {
18 | log = new Mock();
19 | };
20 |
21 | context["When WebServer does not have access to the port"] = () =>
22 | {
23 | before = () =>
24 | {
25 | webServer = new Mock();
26 | webServer.Setup(x => x.Start())
27 | .Throws(new WebCorePortException());
28 | };
29 |
30 | it["Gives the user a helpful error message"] = () =>
31 | {
32 | Program.RunWebServer(webServer.Object, log.Object, new ManualResetEvent(true));
33 | log.Verify(
34 | x => x.Error(
35 | It.Is(message => message.StartsWith("Please allow the user to access the port. eg. 'netsh http add urlacl url=http://*:9999/ user=")),
36 | It.IsAny()
37 | )
38 | );
39 | };
40 | };
41 | };
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/Specs/WebConfigTest.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Xml;
3 | using NSpec;
4 |
5 | namespace WebAppServer.Tests.Specs
6 | {
7 | class WebConfigTest : nspec
8 | {
9 | public string GetTemporaryDirectory()
10 | {
11 | string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
12 | Directory.CreateDirectory(tempDirectory);
13 | return tempDirectory;
14 | }
15 |
16 | public const string DefaultRootWebConfig = @"
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | ";
26 |
27 | public string RootWebConfigPath()
28 | {
29 | var file = Path.Combine(GetTemporaryDirectory(), "web.config");
30 | File.WriteAllText(file, DefaultRootWebConfig);
31 | return file;
32 | }
33 |
34 | void describe_()
35 | {
36 | describe["WebConfig"] = () =>
37 | {
38 | string baseDir = "";
39 | string rootWebConfigPath = "";
40 |
41 | before = () =>
42 | {
43 | baseDir = GetTemporaryDirectory();
44 | Directory.CreateDirectory(Path.Combine(baseDir, "config"));
45 | rootWebConfigPath = RootWebConfigPath();
46 | };
47 |
48 | after = () =>
49 | {
50 | Directory.Delete(baseDir, true);
51 | File.Delete(rootWebConfigPath);
52 | };
53 |
54 | it["Creates a new configuration file"] = () =>
55 | {
56 | var webConfigPath = WebConfig.Create(rootWebConfigPath, baseDir);
57 | webConfigPath.should_contain(baseDir);
58 | var doc = new XmlDocument();
59 | doc.Load(webConfigPath);
60 | XmlAttribute[] attributes = new XmlAttribute[1];
61 | doc.SelectSingleNode("//configuration/system.web/compilation").Attributes.CopyTo(attributes, 0);
62 | attributes.Length.should_be(1);
63 | attributes[0].Value.should_be(Path.Combine(baseDir, "tmp"));
64 | attributes[0].Name.should_be("tempDirectory");
65 | };
66 | };
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/Test.nunit:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/WebAppServer.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {74217BBF-73AF-4F95-9116-FA86C9830718}
8 | Library
9 | Properties
10 | WebAppServer.Tests
11 | WebAppServer.Tests
12 | v4.5
13 | 512
14 | ..\
15 | true
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\packages\Moq.4.2.1409.1722\lib\net40\Moq.dll
37 |
38 |
39 | ..\packages\nspec.0.9.68\lib\NSpec.dll
40 |
41 |
42 |
43 |
44 |
45 | False
46 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | PreserveNewest
77 |
78 |
79 |
80 |
81 | {dc9f6edc-5779-481c-9424-7c4cd63620b3}
82 | WebAppServer
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
91 |
92 |
93 |
94 |
101 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/WebAppServer.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/WebAppServer/ConfigGenerator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Security.Cryptography;
4 | using System.Text;
5 | using System.Xml.Linq;
6 | using System.Xml.XPath;
7 | using WebAppServer.Properties;
8 |
9 | namespace WebAppServer
10 | {
11 | public class ConfigSettings
12 | {
13 | public string RootWebConfigPath { get; set; }
14 | public string AppConfigPath { get; set; }
15 | public uint Port { get; set; }
16 |
17 | }
18 |
19 | public class ConfigGenerator : IDisposable
20 | {
21 | private readonly string configPath;
22 | private readonly string webRootPath;
23 | private readonly string logsRootPath;
24 | private readonly string tempPath;
25 |
26 | public ConfigGenerator(string webRoot)
27 | {
28 | if (string.IsNullOrWhiteSpace(webRoot))
29 | {
30 | throw new ArgumentNullException("webRoot");
31 | }
32 | this.webRootPath = webRoot;
33 |
34 | var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
35 | configPath = Path.Combine(baseDirectory, "config");
36 | logsRootPath = Path.Combine(baseDirectory, "log");
37 | tempPath = Path.Combine(baseDirectory, "tmp");
38 |
39 | EnsureDirectory(configPath);
40 | EnsureDirectory(logsRootPath);
41 | EnsureDirectory(tempPath);
42 | }
43 |
44 | ///
45 | ///
46 | ///
47 | /// The application port
48 | /// The to the framework's root web.config based on runtime version
49 | /// One of the Constants.RuntimeVersion values.
50 | /// One of the Constants.PipelineMode values.
51 | ///
52 | public ConfigSettings Create(uint port, string rootWebConfigPath, string runtimeVersion, string pipelineMode, string userName, string password)
53 | {
54 |
55 | var settings = new ConfigSettings
56 | {
57 | Port = port,
58 | RootWebConfigPath = Environment.ExpandEnvironmentVariables(rootWebConfigPath),
59 | AppConfigPath = Path.Combine(configPath, "applicationHost.config")
60 | };
61 |
62 | var clrConfigPath = Path.Combine(configPath, "aspnet.config"); // TODO: might need to just -> runtime version aspnet.config file
63 |
64 | File.WriteAllText(clrConfigPath, Resources.aspnet);
65 | File.WriteAllText(settings.AppConfigPath, runtimeVersion == Constants.RuntimeVersion.VersionFourDotZero ? Resources.applicationhost : Resources.v2_0AppHost);
66 |
67 | // TODO: Randomize AES Session Keys??
68 | // TODO: Generage new machine key - use BuildMachineKeyElement()
69 | // TODO: /configuration/system.webServer/security/authentication/anonymousAuthentication[username] = sandbox username or just IUSR?
70 |
71 | var appHostConfig = XDocument.Load(settings.AppConfigPath);
72 |
73 | // set the application pools config files
74 | var appPoolName = "AppPool" + port;
75 | appHostConfig.XPathSelectElement(Constants.ConfigXPath.AppPools).RemoveNodes();
76 | appHostConfig.AddToElement(Constants.ConfigXPath.AppPools,
77 | BuildApplicationPool(appPoolName, runtimeVersion, pipelineMode, clrConfigPath, userName, password));
78 |
79 | // disable http logging
80 | appHostConfig.SetValue(Constants.ConfigXPath.WebServer + "/httpLogging", "dontLog", true);
81 |
82 | // add the site and settings to the app host config
83 | appHostConfig.AddToElement(Constants.ConfigXPath.Sites, BuildSiteElement("IronFoundrySite", webRootPath, appPoolName, port));
84 |
85 | appHostConfig.SetValue(Constants.ConfigXPath.Sites + "/applicationDefaults", "applicationPool", appPoolName);
86 | appHostConfig.SetValue(Constants.ConfigXPath.Sites + "/virtualDirectoryDefaults", "allowSubDirConfig", true);
87 |
88 | appHostConfig.Save(settings.AppConfigPath);
89 | return settings;
90 | }
91 |
92 | private void EnsureDirectory(string directory)
93 | {
94 | if (!Directory.Exists(directory))
95 | {
96 | Directory.CreateDirectory(directory);
97 | }
98 | }
99 |
100 | protected virtual XElement BuildApplicationPool(
101 | string name, string runtimeVersion,
102 | string pipelineMode, string configFile,
103 | string userName, string password)
104 | {
105 | var pool = new XElement("add");
106 | pool.Add(new XAttribute("name", name));
107 | pool.Add(new XAttribute("managedRuntimeVersion", runtimeVersion));
108 | pool.Add(new XAttribute("managedPipelineMode", pipelineMode));
109 | pool.Add(new XAttribute("CLRConfigFile", configFile));
110 | pool.Add(new XAttribute("autoStart", true));
111 | pool.Add(new XAttribute("startMode", "AlwaysRunning"));
112 |
113 | if (!(string.IsNullOrWhiteSpace(userName) || string.IsNullOrWhiteSpace(password)))
114 | {
115 | var processModel = new XElement("processModel");
116 | processModel.Add(new XAttribute("identityType", "SpecificUser"));
117 | processModel.Add(new XAttribute("userName", userName));
118 | processModel.Add(new XAttribute("password", password));
119 | processModel.Add(new XAttribute("manualGroupMembership", "true"));
120 | pool.Add(processModel);
121 | }
122 |
123 | return pool;
124 | }
125 |
126 | protected virtual XElement BuildMachineKeyElement()
127 | {
128 | Func keyGen = length =>
129 | {
130 | var buff = new Byte[length];
131 | new RNGCryptoServiceProvider().GetBytes(buff);
132 | var sb = new StringBuilder(length * 2);
133 | foreach (byte t in buff)
134 | {
135 | sb.AppendFormat("{0:X2}", t);
136 | }
137 | return sb.ToString();
138 | };
139 |
140 | var node = new XElement("machineKey");
141 | node.Add(new XAttribute("validationKey", keyGen(64)));
142 | node.Add(new XAttribute("decryptionKey", keyGen(32)));
143 | node.Add(new XAttribute("validation", "SHA1"));
144 | node.Add(new XAttribute("decryption", "AES"));
145 | return node;
146 | }
147 |
148 | protected virtual XElement BuildSiteElement(string name, string physicalPath, string appPoolName, uint port)
149 | {
150 | var site = new XElement("site");
151 | site.Add(new XAttribute("name", name));
152 | site.Add(new XAttribute("id", 1));
153 | site.Add(new XAttribute("serverAutoStart", true));
154 | site.Add(BuildApplicationElement("/", physicalPath, appPoolName));
155 | site.Add(new XElement("bindings", BuildBindingElement("http", port, String.Empty))); // "localhost" vs String.Empty for local ONLY binding
156 | return site;
157 | }
158 |
159 | protected virtual XElement BuildApplicationElement(string path, string physicalPath, string applicationPool)
160 | {
161 | var app = new XElement("application");
162 | app.Add(new XAttribute("path", path));
163 | app.Add(new XAttribute("applicationPool", applicationPool));
164 | app.Add(BuildVirtualDirectoryElement("/", physicalPath));
165 | return app;
166 | }
167 |
168 | protected virtual XElement BuildVirtualDirectoryElement(string path, string physicalPath)
169 | {
170 | var vDir = new XElement("virtualDirectory");
171 | vDir.Add(new XAttribute("path", path));
172 | vDir.Add(new XAttribute("physicalPath", physicalPath));
173 | return vDir;
174 | }
175 |
176 | protected virtual XElement BuildBindingElement(string protocol, uint port, string host)
177 | {
178 | var binding = new XElement("binding");
179 | binding.Add(new XAttribute("protocol", protocol));
180 | binding.Add(new XAttribute("bindingInformation", String.Format("*:{0}:{1}", port, host)));
181 | return binding;
182 | }
183 |
184 | public void Dispose()
185 | {
186 | if (Directory.Exists(configPath))
187 | {
188 | Directory.Delete(configPath, true);
189 | }
190 | }
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/WebAppServer/Constants.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace WebAppServer
6 | {
7 | public class Constants
8 | {
9 | public class ConfigXPath
10 | {
11 | public static string ApplicationHost = "/configuration/system.applicationHost";
12 | public static string AppPools = ApplicationHost + "/applicationPools";
13 | public static string Sites = ApplicationHost + "/sites";
14 | public static string SiteDefaults = Sites + "/siteDefaults";
15 |
16 | public static string WebServer = "/configuration/system.webServer";
17 | }
18 |
19 | public class FrameworkPaths
20 | {
21 | public static string TwoDotZero = @"%windir%\Microsoft.NET\Framework\v2.0.50727";
22 | public static string FourDotZero = @"%windir%\Microsoft.NET\Framework\v4.0.30319";
23 |
24 | public static string TwoDotZeroWebConfig = TwoDotZero + @"\Config\web.config";
25 | public static string FourDotZeroWebConfig = FourDotZero + @"\Config\web.config";
26 | }
27 |
28 | public class RuntimeVersion
29 | {
30 | public static string VersionFourDotZero = "v4.0";
31 | public static string VersionTwoDotZero = "v2.0";
32 | }
33 |
34 | public class PipelineMode
35 | {
36 | public static string Integrated = "Integrated";
37 | public static string Classic = "Classic";
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/WebAppServer/Logger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 |
6 | namespace WebAppServer
7 | {
8 | public class Logger
9 | {
10 | public virtual void Info(string messageFormat, params object[] args)
11 | {
12 | Console.Out.WriteLine(DateTimeOffset.UtcNow.ToString("u") + "|INFO|" + messageFormat, args);
13 | }
14 |
15 | public virtual void Error(string messageFormat, params object[] args)
16 | {
17 | Console.Error.WriteLine(DateTimeOffset.UtcNow.ToString("u") + "|ERROR|" + messageFormat, args);
18 | }
19 |
20 | public virtual void ErrorException(string message, Exception exception)
21 | {
22 | Error(message);
23 | Error(exception.ToString());
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/WebAppServer/Options.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace WebAppServer
8 | {
9 | public class Options
10 | {
11 | public uint Port { get; set; }
12 | public string WebRoot { get; set; }
13 |
14 | public void Parse(string[] args)
15 | {
16 | Console.Out.WriteLine("PORT == {0}", Environment.GetEnvironmentVariable("PORT"));
17 |
18 | Port = uint.Parse(Environment.GetEnvironmentVariable("PORT"));
19 | WebRoot = Path.GetFullPath(".");
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/WebAppServer/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Security.Principal;
5 | using System.Threading;
6 |
7 | namespace WebAppServer
8 | {
9 | public static class Program
10 | {
11 | private static readonly Logger log = new Logger();
12 | private static readonly ManualResetEvent exitLatch = new ManualResetEvent(false);
13 |
14 | public static int RunWebServer(IWebServer webServer, Logger log, ManualResetEvent exitLatch)
15 | {
16 | try
17 | {
18 | log.Info("Starting web server instance...");
19 | webServer.Start();
20 | Console.WriteLine("Server Started.... press CTRL + C to stop");
21 | Warmup(webServer);
22 | exitLatch.WaitOne();
23 | Console.WriteLine("Server shutting down, please wait...");
24 | webServer.Stop();
25 |
26 | return 0;
27 | }
28 | catch (WebCorePortException)
29 | {
30 | log.Error("Please allow the user to access the port. eg. 'netsh http add urlacl url=http://*:9999/ user={0}'", WindowsIdentity.GetCurrent().Name);
31 | return 1;
32 | }
33 | }
34 |
35 | private static void Warmup(IWebServer server)
36 | {
37 | var req = WebRequest.Create("http://localhost:" + server.Port);
38 | req.Timeout = 1000;
39 | try
40 | {
41 | req.GetResponse();
42 | }
43 | catch (WebException ex)
44 | {
45 | // ignore exceptions. An exception can be thrown if a 404 was returned
46 | // which is a possibility if the application doesn't have `~/' endpoint
47 | }
48 | }
49 |
50 | private static int Main(string[] args)
51 | {
52 | Console.CancelKeyPress += (s, e) =>
53 | {
54 | e.Cancel = true;
55 | exitLatch.Set();
56 | };
57 |
58 | Console.Error.WriteLine("The use of WebAppServer.exe is deprecated. Please use the hwc-buildpack instead.");
59 |
60 | var exitCode = 0;
61 | try
62 | {
63 | var options = new Options();
64 | options.Parse(args);
65 |
66 | log.Info("Port:{0}", options.Port);
67 | log.Info("Webroot:{0}", options.WebRoot);
68 |
69 | var configGenerator = new ConfigGenerator(options.WebRoot);
70 | var webConfig = WebConfig.Create(Environment.ExpandEnvironmentVariables(Constants.FrameworkPaths.FourDotZeroWebConfig),
71 | AppDomain.CurrentDomain.BaseDirectory);
72 | var settings = configGenerator.Create(
73 | options.Port,
74 | webConfig,
75 | Constants.RuntimeVersion.VersionFourDotZero,
76 | Constants.PipelineMode.Integrated,
77 | null,
78 | null);
79 |
80 | using (var webServer = new WebServer(settings))
81 | {
82 | exitCode = RunWebServer(webServer, log, exitLatch);
83 | }
84 | }
85 | catch (Exception ex)
86 | {
87 | log.ErrorException("Error on startup.", ex);
88 | exitCode = 1;
89 | }
90 |
91 | return exitCode;
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/WebAppServer/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: AssemblyTitle("WebAppServer")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("WebAppServer")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("2c27e47c-20f3-489d-8378-fbb026faba8f")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/WebAppServer/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.34014
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace WebAppServer.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WebAppServer.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8"?>
65 | ///<configuration>
66 | ///
67 | /// <configSections>
68 | /// <sectionGroup name="system.applicationHost">
69 | /// <section name="applicationPools" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
70 | /// <section name="configHistory" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
71 | /// <section name="customMetadata" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
72 | /// <section name="listenerAdapters" allowDefinition="AppHostOnly" overrideModeDefault [rest of string was truncated]";.
73 | ///
74 | internal static string applicationhost {
75 | get {
76 | return ResourceManager.GetString("applicationhost", resourceCulture);
77 | }
78 | }
79 |
80 | ///
81 | /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" ?>
82 | ///<configuration>
83 | /// <runtime>
84 | /// <legacyUnhandledExceptionPolicy enabled="false" />
85 | /// <legacyImpersonationPolicy enabled="true"/>
86 | /// <alwaysFlowImpersonationPolicy enabled="false"/>
87 | /// <SymbolReadingPolicy enabled="1" />
88 | /// </runtime>
89 | /// <startup useLegacyV2RuntimeActivationPolicy="true" />
90 | ///</configuration>
91 | ///.
92 | ///
93 | internal static string aspnet {
94 | get {
95 | return ResourceManager.GetString("aspnet", resourceCulture);
96 | }
97 | }
98 |
99 | ///
100 | /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8"?>
101 | ///
102 | ///<configuration>
103 | ///
104 | /// <configSections>
105 | /// <sectionGroup name="system.applicationHost">
106 | /// <section name="applicationPools" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
107 | /// <section name="configHistory" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
108 | /// <section name="customMetadata" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
109 | /// <section name="listenerAdapters" allowDefinition="AppHostOnly" overrideModeDefau [rest of string was truncated]";.
110 | ///
111 | internal static string v2_0AppHost {
112 | get {
113 | return ResourceManager.GetString("v2_0AppHost", resourceCulture);
114 | }
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/WebAppServer/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\applicationhost.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
123 |
124 |
125 | ..\resources\aspnet.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
126 |
127 |
128 | ..\Resources\v2.0AppHost.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
129 |
130 |
--------------------------------------------------------------------------------
/WebAppServer/Readme.txt:
--------------------------------------------------------------------------------
1 | Configuring HTTP.SYS
2 | ------------------------------------------------------
3 | http://msdn.microsoft.com/en-us/library/ms733768.aspx
4 | netsh http add urlacl url=http://foobar:port/ user=containerUser
5 | netsh http delete urlacl url=http://foobar:port/ user=containerUser
6 |
7 | Hostable Web Core
8 | ------------------------------------------------------
9 | API Ref: http://msdn.microsoft.com/en-us/library/ms693832(v=vs.90).aspx
10 | Walkthrough: http://msdn.microsoft.com/en-us/library/ms689327(v=vs.90).aspx
11 | Runtime errors show up in windows application event log, source = HostableWebCore
12 |
13 | Note that WebcoreActivate and WebcoreShutdown can be called only once in process lifetime.
14 | Also HWC always uses .Net 2.0 schema and there is no way to make it pick .Net 4.0 schema.
15 | So root web.config passed to WebcoreActivate cannot have properties which are only supported
16 | in .Net 4.0. This problem will be fixed in Win8.
17 |
18 | Notes:
19 | -----------------------------------------------------
20 | - On Windows 7, you can only use .net 2.0 runtime version
21 | (read above for explanation, this is hostable web core limitation).
22 |
23 | given the following args:
24 | -p 8869 -r d:\container -v 2.0 -b true
25 |
26 | It expects your web app to live in: d:\container\www
27 | It will create log in d:\container\log
28 | It will create config in d:\container\config
29 | It will create temp in d:\container\tmp
--------------------------------------------------------------------------------
/WebAppServer/Resources/aspnet.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/WebAppServer/WebAppServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {DC9F6EDC-5779-481C-9424-7C4CD63620B3}
8 | Exe
9 | Properties
10 | WebAppServer
11 | WebAppServer
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | false
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\
31 | TRACE
32 | prompt
33 | 4
34 | false
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | True
51 | True
52 | Resources.resx
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | Designer
62 | ResXFileCodeGenerator
63 | Resources.Designer.cs
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
80 |
--------------------------------------------------------------------------------
/WebAppServer/WebConfig.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Xml;
3 |
4 | namespace WebAppServer
5 | {
6 | public class WebConfig
7 | {
8 | public static string Create(string rootWebConfigPath, string baseDir)
9 | {
10 | var webConfig = Path.Combine(baseDir, "config", "web.config");
11 | File.Copy(rootWebConfigPath, webConfig, true);
12 |
13 | var doc = new XmlDocument();
14 | doc.Load(webConfig);
15 | var tempDirAttr = doc.CreateAttribute("tempDirectory");
16 | tempDirAttr.Value = Path.Combine(baseDir, "tmp");
17 | doc.SelectSingleNode("//configuration/system.web/compilation").Attributes.Append(tempDirAttr);
18 | doc.Save(webConfig);
19 |
20 | return webConfig;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/WebAppServer/WebCoreActivationException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace WebAppServer
6 | {
7 | using System.ComponentModel;
8 |
9 | public class WebCoreActivationException : Exception
10 | {
11 | // ref: http://blogs.iis.net/ksingla/archive/2007/12/20/ins-amp-outs-of-hostable-web-core.aspx
12 | public static readonly Dictionary HResults = new Dictionary
13 | {
14 | {"80070032", "HWC Activation failed - the request is not supported, check application event log for further details."},
15 | {"80070038", "HWC Activation failed - appHostConfig has multiple app pools defined in it"},
16 | {"800700B7", "HWC Activation failed - invalid binding: port/IP in use already or app pool name in use"},
17 | {"80070015", "HWC Activation failed - no websites defined in appHostConfig"},
18 | {"80070044", "HWC Activation failed - app pool defined but site pointing to nonexistend app pool"},
19 | {"8007000D", "HWC Activation failed - All configuration system checks are still valid. So invalid xml in configuration or duplicate site ids in appHostConfig."},
20 | {"80070057", "HWC Activation failed - bad parameter"},
21 | {"80070490", "HWC Activation failed - appHostConfig path is not valid"},
22 | {"80070420", "HWC Activation failed - service already running"}
23 | };
24 |
25 | public WebCoreActivationException(int result) : this(result.ToString("X"), result) { }
26 |
27 | private WebCoreActivationException(string hResult, int result) : base(
28 | HResults.ContainsKey(hResult)
29 | ? new Win32Exception(result).Message + ": " + HResults[hResult]
30 | : new Win32Exception(result).Message)
31 | {
32 | HResult = result;
33 | }
34 | }
35 |
36 | public class WebCorePortException : WebCoreActivationException
37 | {
38 | public WebCorePortException() : base(unchecked((int)WebServer.HostableWebCore.ERROR_ACCESS_DENIED))
39 | {
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/WebAppServer/WebServer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace WebAppServer
6 | {
7 | public interface IWebServer : IDisposable
8 | {
9 | void Start();
10 | void Stop();
11 | uint Port { get; }
12 | }
13 |
14 | // Ref: http://msdn.microsoft.com/en-us/library/ms689327%28v=vs.90%29.aspx
15 | // May require: // netsh http add urlacl url=http://*:PORT/ user=DOMAIN\user
16 | public class WebServer : IWebServer
17 | {
18 | private readonly ConfigSettings configSettings;
19 |
20 | public WebServer(ConfigSettings configSettings)
21 | {
22 | this.configSettings = configSettings;
23 | }
24 |
25 | public void Dispose()
26 | {
27 | Stop();
28 | }
29 |
30 | public void Start()
31 | {
32 | if (!HostableWebCore.IsActivated)
33 | {
34 | HostableWebCore.Activate(configSettings.AppConfigPath, configSettings.RootWebConfigPath, Guid.NewGuid().ToString());
35 | }
36 | }
37 |
38 | public void Stop()
39 | {
40 | if (HostableWebCore.IsActivated)
41 | {
42 | HostableWebCore.Shutdown(false);
43 | }
44 | }
45 |
46 | public uint Port
47 | {
48 | get { return configSettings.Port; }
49 | }
50 |
51 | #region Hostable WebCore
52 | public static class HostableWebCore
53 | {
54 | public const uint ERROR_ACCESS_DENIED = 0x80070005;
55 |
56 | const string HWCPath = @"%windir%\system32\inetsrv\hwebcore.dll";
57 |
58 | private static bool _isActivated;
59 |
60 | private delegate uint FnWebCoreShutdown(bool immediate);
61 | private delegate uint FnWebCoreActivate(
62 | [In, MarshalAs(UnmanagedType.LPWStr)]string appHostConfig,
63 | [In, MarshalAs(UnmanagedType.LPWStr)]string rootWebConfig,
64 | [In, MarshalAs(UnmanagedType.LPWStr)]string instanceName);
65 |
66 | private static readonly FnWebCoreActivate WebCoreActivate;
67 | private static readonly FnWebCoreShutdown WebCoreShutdown;
68 |
69 | static HostableWebCore()
70 | {
71 | var hostableWebCorePath = Environment.ExpandEnvironmentVariables(HWCPath);
72 | if (!File.Exists(hostableWebCorePath))
73 | {
74 | throw new FileNotFoundException("Unable to locate hostable web core library, ensure IIS 7+ is installed", hostableWebCorePath);
75 | }
76 |
77 | // Load the library and get the function pointers for the WebCore entry points
78 | IntPtr hwc = HWCInterop.LoadLibrary(hostableWebCorePath);
79 |
80 | IntPtr procaddr = HWCInterop.GetProcAddress(hwc, "WebCoreActivate");
81 | WebCoreActivate = (FnWebCoreActivate) Marshal.GetDelegateForFunctionPointer(procaddr, typeof(FnWebCoreActivate));
82 |
83 | procaddr = HWCInterop.GetProcAddress(hwc, "WebCoreShutdown");
84 | WebCoreShutdown = (FnWebCoreShutdown) Marshal.GetDelegateForFunctionPointer(procaddr, typeof(FnWebCoreShutdown));
85 | }
86 |
87 | ///
88 | /// Specifies if Hostable WebCore has been activated
89 | ///
90 | public static bool IsActivated
91 | {
92 | get { return _isActivated; }
93 | }
94 |
95 | ///
96 | /// Activate the HWC
97 | ///
98 | /// Path to ApplicationHost.config to use
99 | /// Path to the Root Web.config to use
100 | /// Name for this instance
101 | public static void Activate(string appHostConfig, string rootWebConfig, string instanceName)
102 | {
103 | uint result = WebCoreActivate(appHostConfig, rootWebConfig, instanceName);
104 | if (result != 0)
105 | {
106 | if (result == ERROR_ACCESS_DENIED)
107 | throw new WebCorePortException();
108 |
109 | throw new WebCoreActivationException((int)result);
110 | }
111 |
112 | _isActivated = true;
113 | }
114 |
115 | ///
116 | /// Shutdown HWC
117 | ///
118 | public static void Shutdown(bool immediate)
119 | {
120 | if (_isActivated)
121 | {
122 | WebCoreShutdown(immediate);
123 | _isActivated = false;
124 | }
125 | }
126 |
127 | private static class HWCInterop
128 | {
129 | [DllImport("kernel32.dll", SetLastError = true)]
130 | internal static extern IntPtr LoadLibrary(String dllname);
131 |
132 | [DllImport("kernel32.dll", SetLastError = true)]
133 | internal static extern IntPtr GetProcAddress(IntPtr hModule, String procname);
134 | }
135 | }
136 | #endregion
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/WebAppServer/XmlExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 | using System.Xml.XPath;
3 |
4 | namespace WebAppServer
5 | {
6 | public static class XmlExtensions
7 | {
8 | public static void SetValue(this XDocument root, string elementSelector, string attributeName, object attributeValue)
9 | {
10 | root.XPathSelectElement(elementSelector).SetAttributeValue(attributeName, attributeValue);
11 | }
12 |
13 | public static void AddToElement(this XDocument root, string elementSelector, object value)
14 | {
15 | root.XPathSelectElement(elementSelector).Add(value);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/WindowsAppLifecycle.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Builder", "Builder\Builder.csproj", "{68F6A408-B0F2-4BB4-A0A4-278694FAB63D}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{08426B53-B9F2-420A-9147-641DFBFE04BE}"
9 | ProjectSection(SolutionItems) = preProject
10 | .nuget\NuGet.Config = .nuget\NuGet.Config
11 | .nuget\NuGet.exe = .nuget\NuGet.exe
12 | .nuget\NuGet.targets = .nuget\NuGet.targets
13 | EndProjectSection
14 | EndProject
15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Launcher.Tests", "Launcher.Tests\Launcher.Tests.csproj", "{273733E4-6283-4E52-9CED-10EFA609EB38}"
16 | ProjectSection(ProjectDependencies) = postProject
17 | {956F7FAD-B936-4ED7-9685-4D963E4CBDD6} = {956F7FAD-B936-4ED7-9685-4D963E4CBDD6}
18 | EndProjectSection
19 | EndProject
20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebAppServer", "WebAppServer\WebAppServer.csproj", "{DC9F6EDC-5779-481C-9424-7C4CD63620B3}"
21 | EndProject
22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebAppServer.Tests", "WebAppServer.Tests\WebAppServer.Tests.csproj", "{74217BBF-73AF-4F95-9116-FA86C9830718}"
23 | EndProject
24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Launcher", "Launcher\Launcher.csproj", "{956F7FAD-B936-4ED7-9685-4D963E4CBDD6}"
25 | EndProject
26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Builder.Tests", "Builder.Tests\Builder.Tests.csproj", "{2FE7925C-AC3E-4103-BF03-2D22F3D88610}"
27 | EndProject
28 | Global
29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
30 | Debug|Any CPU = Debug|Any CPU
31 | Release|Any CPU = Release|Any CPU
32 | EndGlobalSection
33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
34 | {68F6A408-B0F2-4BB4-A0A4-278694FAB63D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {68F6A408-B0F2-4BB4-A0A4-278694FAB63D}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {68F6A408-B0F2-4BB4-A0A4-278694FAB63D}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {68F6A408-B0F2-4BB4-A0A4-278694FAB63D}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {273733E4-6283-4E52-9CED-10EFA609EB38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {273733E4-6283-4E52-9CED-10EFA609EB38}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {273733E4-6283-4E52-9CED-10EFA609EB38}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {273733E4-6283-4E52-9CED-10EFA609EB38}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {DC9F6EDC-5779-481C-9424-7C4CD63620B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {DC9F6EDC-5779-481C-9424-7C4CD63620B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {DC9F6EDC-5779-481C-9424-7C4CD63620B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {DC9F6EDC-5779-481C-9424-7C4CD63620B3}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {74217BBF-73AF-4F95-9116-FA86C9830718}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47 | {74217BBF-73AF-4F95-9116-FA86C9830718}.Debug|Any CPU.Build.0 = Debug|Any CPU
48 | {74217BBF-73AF-4F95-9116-FA86C9830718}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 | {74217BBF-73AF-4F95-9116-FA86C9830718}.Release|Any CPU.Build.0 = Release|Any CPU
50 | {956F7FAD-B936-4ED7-9685-4D963E4CBDD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 | {956F7FAD-B936-4ED7-9685-4D963E4CBDD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 | {956F7FAD-B936-4ED7-9685-4D963E4CBDD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
53 | {956F7FAD-B936-4ED7-9685-4D963E4CBDD6}.Release|Any CPU.Build.0 = Release|Any CPU
54 | {2FE7925C-AC3E-4103-BF03-2D22F3D88610}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55 | {2FE7925C-AC3E-4103-BF03-2D22F3D88610}.Debug|Any CPU.Build.0 = Debug|Any CPU
56 | {2FE7925C-AC3E-4103-BF03-2D22F3D88610}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 | {2FE7925C-AC3E-4103-BF03-2D22F3D88610}.Release|Any CPU.Build.0 = Release|Any CPU
58 | EndGlobalSection
59 | GlobalSection(SolutionProperties) = preSolution
60 | HideSolutionNode = FALSE
61 | EndGlobalSection
62 | EndGlobal
63 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 0.{build}
2 | skip_tags: true
3 | cache: C:\Users\appveyor\AppData\Local\NuGet\Cache
4 | build_script:
5 | - git submodule update --init --recursive
6 | - scripts\make.bat
7 | test: off
8 | artifacts:
9 | - path: output/*
10 | name: lifecycle
11 | deploy:
12 | - provider: S3
13 | access_key_id: AKIAI2AAY3LUVTHYDTDA
14 | secret_access_key:
15 | secure: zNBMp5HGSOJLlSY+lBKwgWH5eE71tYCWST8QQjXO+IwIE2pDeI/uv5Nm0iBwob4K
16 | region: us-east-1
17 | bucket: build-windows-app-lifecycle
18 | artifact: lifecycle
19 | set_public: true
20 | on:
21 | branch: master
22 | branches:
23 | only:
24 | - master
25 | - /appveyor/
26 |
--------------------------------------------------------------------------------
/bin/bsdtar.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/bin/bsdtar.exe
--------------------------------------------------------------------------------
/bin/nuget.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/bin/nuget.exe
--------------------------------------------------------------------------------
/scripts/make.bat:
--------------------------------------------------------------------------------
1 | :: msbuild must be in path
2 | SET PATH=%PATH%;%WINDIR%\Microsoft.NET\Framework64\v4.0.30319;%WINDIR%\SysNative
3 | where msbuild
4 | if errorLevel 1 ( echo "msbuild was not found on PATH" && exit /b 1 )
5 |
6 | :: enable some features
7 | dism /online /Enable-Feature /FeatureName:IIS-WebServer /All /NoRestart
8 | dism /online /Enable-Feature /FeatureName:IIS-WebSockets /All /NoRestart
9 | dism /online /Enable-Feature /FeatureName:Application-Server-WebServer-Support /FeatureName:AS-NET-Framework /All /NoRestart
10 | dism /online /Enable-Feature /FeatureName:IIS-HostableWebCore /All /NoRestart
11 |
12 | rmdir /S /Q output
13 | rmdir /S /Q packages
14 | bin\nuget restore || exit /b 1
15 |
16 | MSBuild WindowsAppLifecycle.sln /t:Rebuild /p:Configuration=Release || exit /b 1
17 | packages\nspec.0.9.68\tools\NSpecRunner.exe Builder.Tests\bin\Release\BuilderTests.dll || exit /b 1
18 | packages\nspec.0.9.68\tools\NSpecRunner.exe Launcher.Tests\bin\Release\LauncherTests.dll || exit /b 1
19 | packages\nspec.0.9.68\tools\NSpecRunner.exe WebAppServer.Tests\bin\Release\WebAppServer.Tests.dll || exit /b 1
20 | bin\bsdtar -czvf windows_app_lifecycle.tgz --exclude log -C Builder\bin . -C ..\..\Launcher\bin . -C ..\..\WebAppServer\bin . || exit /b 1
21 | for /f "tokens=*" %%a in ('git rev-parse --short HEAD') do (
22 | set VAR=%%a
23 | )
24 |
25 | mkdir output
26 | move /Y windows_app_lifecycle.tgz output\windows_app_lifecycle-%VAR%.tgz || exit /b 1
27 |
--------------------------------------------------------------------------------
/vendor/CommandLineParser.1.9.71.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/vendor/CommandLineParser.1.9.71.nupkg
--------------------------------------------------------------------------------
/vendor/Newtonsoft.Json.8.0.3.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/vendor/Newtonsoft.Json.8.0.3.nupkg
--------------------------------------------------------------------------------
/vendor/YamlDotNet.3.8.0.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/vendor/YamlDotNet.3.8.0.nupkg
--------------------------------------------------------------------------------
/vendor/nspec.0.9.68.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudfoundry-attic/windows_app_lifecycle/686f5c2e682410b23c29163bd02765ace79a60a6/vendor/nspec.0.9.68.nupkg
--------------------------------------------------------------------------------