1
1
using System . CommandLine ;
2
2
using Microsoft . NET . Build . Containers ;
3
3
using System . Text . Json ;
4
+ using System . CommandLine . Parsing ;
4
5
5
- var fileOption = new Argument < DirectoryInfo > (
6
- name : "folder " ,
7
- description : "The folder to pack ." )
6
+ var publishDirectoryArg = new Argument < DirectoryInfo > (
7
+ name : "PublishDirectory " ,
8
+ description : "The directory for the build outputs to be published ." )
8
9
. LegalFilePathsOnly ( ) . ExistingOnly ( ) ;
9
10
10
- Option < string > registryUri = new (
11
- name : "--registry" ,
12
- description : "Location of the registry to push to." ,
13
- getDefaultValue : ( ) => "localhost:5010" ) ;
14
-
15
- Option < string > baseImageName = new (
16
- name : "--base" ,
17
- description : "Base image name." ,
18
- getDefaultValue : ( ) => "dotnet/runtime" ) ;
11
+ var baseRegistryOpt = new Option < string > (
12
+ name : "--baseregistry" ,
13
+ description : "The registry to use for the base image." )
14
+ {
15
+ IsRequired = true
16
+ } ;
19
17
20
- Option < string > baseImageTag = new (
21
- name : "--baseTag" ,
22
- description : "Base image tag." ,
23
- getDefaultValue : ( ) => $ "{ System . Runtime . InteropServices . RuntimeInformation . FrameworkDescription [ 5 ] } .0") ;
18
+ var baseImageNameOpt = new Option < string > (
19
+ name : "--baseimagename" ,
20
+ description : "The base image to pull." )
21
+ {
22
+ IsRequired = true
23
+ } ;
24
24
25
- Option < string [ ] > entrypoint = new (
26
- name : "--entrypoint" ,
27
- description : "Entrypoint application command." ) ;
25
+ var baseImageTagOpt = new Option < string > (
26
+ name : "--baseimagetag" ,
27
+ description : "The base image tag. Ex: 6.0" ,
28
+ getDefaultValue : ( ) => "latest" ) ;
28
29
29
- Option < string > imageName = new (
30
- name : "--name" ,
31
- description : "Name of the new image." ) ;
30
+ var outputRegistryOpt = new Option < string > (
31
+ name : "--outputregistry" ,
32
+ description : "The registry to push to." )
33
+ {
34
+ IsRequired = true
35
+ } ;
32
36
33
- var imageTag = new Option < string > ( "--tag" , description : "Tag of the new image." , getDefaultValue : ( ) => "latest" ) ;
37
+ var imageNameOpt = new Option < string > (
38
+ name : "--imagename" ,
39
+ description : "The name of the output image that will be pushed to the registry." )
40
+ {
41
+ IsRequired = true
42
+ } ;
34
43
35
- var workingDir = new Option < string > ( "--working-dir" , description : "The working directory of the application" , getDefaultValue : ( ) => "/app" ) ;
44
+ var imageTagsOpt = new Option < string [ ] > (
45
+ name : "--imagetags" ,
46
+ description : "The tags to associate with the new image." ) ;
36
47
37
- RootCommand rootCommand = new ( "Containerize an application without Docker." ) {
38
- fileOption ,
39
- registryUri ,
40
- baseImageName ,
41
- baseImageTag ,
42
- entrypoint ,
43
- imageName ,
44
- imageTag ,
45
- workingDir
46
- } ;
47
- rootCommand . SetHandler ( async ( folder , containerWorkingDir , uri , baseImageName , baseTag , entrypoint , imageName , imageTag ) =>
48
- {
49
- await Containerize ( folder , containerWorkingDir , uri , baseImageName , baseTag , entrypoint , imageName , imageTag ) ;
50
- } ,
51
- fileOption ,
52
- workingDir ,
53
- registryUri ,
54
- baseImageName ,
55
- baseImageTag ,
56
- entrypoint ,
57
- imageName ,
58
- imageTag
59
- ) ;
60
-
61
- return await rootCommand . InvokeAsync ( args ) ;
62
-
63
- async Task Containerize ( DirectoryInfo folder , string workingDir , string registryName , string baseName , string baseTag , string [ ] entrypoint , string imageName , string imageTag )
48
+ var workingDirectoryOpt = new Option < string > (
49
+ name : "--workingdirectory" ,
50
+ description : "The working directory of the container." )
64
51
{
65
- Registry registry = new Registry ( new Uri ( $ "http://{ registryName } ") ) ;
52
+ IsRequired = true
53
+ } ;
66
54
67
- Console . WriteLine ( $ "Reading from { registry . BaseUri } ") ;
55
+ var entrypointOpt = new Option < string [ ] > (
56
+ name : "--entrypoint" ,
57
+ description : "The entrypoint application of the container." )
58
+ {
59
+ IsRequired = true
60
+ } ;
68
61
69
- Image x = await registry . GetImageManifest ( baseName , baseTag ) ;
70
- x . WorkingDirectory = workingDir ;
62
+ var entrypointArgsOpt = new Option < string [ ] > (
63
+ name : "--entrypointargs" ,
64
+ description : "Arguments to pass alongside Entrypoint." ) ;
71
65
72
- JsonSerializerOptions options = new ( )
66
+ var labelsOpt = new Option < string [ ] > (
67
+ name : "--labels" ,
68
+ description : "Labels that the image configuration will include in metadata." ,
69
+ parseArgument : result =>
73
70
{
74
- WriteIndented = true ,
75
- } ;
76
-
77
- Console . WriteLine ( $ "Copying from { folder . FullName } to { workingDir } ") ;
78
- Layer l = Layer . FromDirectory ( folder . FullName , workingDir ) ;
79
-
80
- x . AddLayer ( l ) ;
81
-
82
- x . SetEntrypoint ( entrypoint ) ;
83
-
84
- // File.WriteAllTextAsync("manifest.json", x.manifest.ToJsonString(options));
85
- // File.WriteAllTextAsync("config.json", x.config.ToJsonString(options));
71
+ var labels = result . Tokens . Select ( x => x . Value ) . ToArray ( ) ;
72
+ var badLabels = labels . Where ( ( v ) => v . Split ( '=' ) . Length != 2 ) ;
73
+
74
+ // Is there a non-zero number of Labels that didn't split into two elements? If so, assume invalid input and error out
75
+ if ( badLabels . Count ( ) != 0 )
76
+ {
77
+ result . ErrorMessage = "Incorrectly formatted labels: " + badLabels . Aggregate ( ( x , y ) => x = x + ";" + y ) ;
78
+
79
+ return new string [ ] { } ;
80
+ }
81
+ return labels ;
82
+ } )
83
+ {
84
+ AllowMultipleArgumentsPerToken = true
85
+ } ;
86
86
87
- await LocalDocker . Load ( x , imageName , imageTag , baseName ) ;
87
+ RootCommand root = new RootCommand ( "Containerize an application without Docker." )
88
+ {
89
+ publishDirectoryArg ,
90
+ baseRegistryOpt ,
91
+ baseImageNameOpt ,
92
+ baseImageTagOpt ,
93
+ outputRegistryOpt ,
94
+ imageNameOpt ,
95
+ imageTagsOpt ,
96
+ workingDirectoryOpt ,
97
+ entrypointOpt ,
98
+ entrypointArgsOpt ,
99
+ labelsOpt
100
+ } ;
88
101
89
- Console . WriteLine ( $ "Loaded image into local Docker daemon. Use 'docker run --rm -it --name { imageName } { registryName } /{ imageName } :{ imageTag } ' to run the application.") ;
90
- }
102
+ root . SetHandler ( async ( context ) =>
103
+ {
104
+ DirectoryInfo _publishDir = context . ParseResult . GetValueForArgument ( publishDirectoryArg ) ;
105
+ string _baseReg = context . ParseResult . GetValueForOption ( baseRegistryOpt ) ?? "" ;
106
+ string _baseName = context . ParseResult . GetValueForOption ( baseImageNameOpt ) ?? "" ;
107
+ string _baseTag = context . ParseResult . GetValueForOption ( baseImageTagOpt ) ?? "" ;
108
+ string _outputReg = context . ParseResult . GetValueForOption ( outputRegistryOpt ) ?? "" ;
109
+ string _name = context . ParseResult . GetValueForOption ( imageNameOpt ) ?? "" ;
110
+ string [ ] _tags = context . ParseResult . GetValueForOption ( imageTagsOpt ) ?? Array . Empty < string > ( ) ;
111
+ string _workingDir = context . ParseResult . GetValueForOption ( workingDirectoryOpt ) ?? "" ;
112
+ string [ ] _entrypoint = context . ParseResult . GetValueForOption ( entrypointOpt ) ?? Array . Empty < string > ( ) ;
113
+ string [ ] _entrypointArgs = context . ParseResult . GetValueForOption ( entrypointArgsOpt ) ?? Array . Empty < string > ( ) ;
114
+ string [ ] _labels = context . ParseResult . GetValueForOption ( labelsOpt ) ?? Array . Empty < string > ( ) ;
115
+
116
+ await ContainerHelpers . Containerize ( _publishDir , _workingDir , _baseReg , _baseName , _baseTag , _entrypoint , _entrypointArgs , _name , _tags , _outputReg , _labels ) ;
117
+ } ) ;
118
+
119
+ return await root . InvokeAsync ( args ) ;
0 commit comments