Skip to content

Commit a53f90c

Browse files
timheuerbaronfel
andauthored
Add support for Labels to the Image config (#120)
* Add support for Labels in metadata, fixes #95 Co-authored-by: Chet Husk <[email protected]>
1 parent 3eb955c commit a53f90c

File tree

3 files changed

+71
-9
lines changed

3 files changed

+71
-9
lines changed

Microsoft.NET.Build.Containers/CreateNewImage.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ public class CreateNewImage : Microsoft.Build.Utilities.Task
6666
/// </summary>
6767
public ITaskItem[] EntrypointArgs { get; set; }
6868

69+
/// <summary>
70+
/// Labels that the image configuration will include in metadata
71+
/// </summary>
72+
public ITaskItem[] Labels { get; set; }
73+
6974
public CreateNewImage()
7075
{
7176
BaseRegistry = "";
@@ -78,6 +83,7 @@ public CreateNewImage()
7883
WorkingDirectory = "";
7984
Entrypoint = Array.Empty<ITaskItem>();
8085
EntrypointArgs = Array.Empty<ITaskItem>();
86+
Labels = Array.Empty<ITaskItem>();
8187
}
8288

8389

@@ -112,6 +118,11 @@ public override bool Execute()
112118
image.WorkingDirectory = WorkingDirectory;
113119
image.SetEntrypoint(Entrypoint.Select(i => i.ItemSpec).ToArray(), EntrypointArgs.Select(i => i.ItemSpec).ToArray());
114120

121+
foreach (var label in Labels)
122+
{
123+
image.Label(label.ItemSpec, label.GetMetadata("Value"));
124+
}
125+
115126
if (OutputRegistry.StartsWith("docker://"))
116127
{
117128
try

Microsoft.NET.Build.Containers/Image.cs

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
namespace Microsoft.NET.Build.Containers;
77

8+
record Label(string name, string value);
9+
810
public class Image
911
{
1012
public JsonNode manifest;
@@ -15,12 +17,16 @@ public class Image
1517

1618
internal List<Layer> newLayers = new();
1719

20+
private HashSet<Label> labels;
21+
1822
public Image(JsonNode manifest, JsonNode config, string name, Registry? registry)
1923
{
2024
this.manifest = manifest;
2125
this.config = config;
2226
this.OriginatingName = name;
2327
this.originatingRegistry = registry;
28+
// labels are inherited from the parent image, so we need to seed our new image with them.
29+
this.labels = ReadLabelsFromConfig(config);
2430
}
2531

2632
public IEnumerable<Descriptor> LayerDescriptors
@@ -61,7 +67,39 @@ private void RecalculateDigest()
6167
manifest["config"]!["digest"] = GetDigest(config);
6268
}
6369

64-
static JsonArray ToJsonArray(string[] items) => new JsonArray(items.Where(s => !string.IsNullOrEmpty(s)).Select(s =>(JsonValue) s).ToArray());
70+
private static HashSet<Label> ReadLabelsFromConfig(JsonNode inputConfig)
71+
{
72+
if (inputConfig is JsonObject config && config["Labels"] is JsonObject labelsJson)
73+
{
74+
// read label mappings from object
75+
var labels = new HashSet<Label>();
76+
foreach (var property in labelsJson)
77+
{
78+
if (property.Key is { } propertyName && property.Value is JsonValue propertyValue)
79+
{
80+
labels.Add(new(propertyName, propertyValue.ToString()));
81+
}
82+
}
83+
return labels;
84+
}
85+
else
86+
{
87+
// initialize and empty labels map
88+
return new HashSet<Label>();
89+
}
90+
}
91+
92+
private JsonObject CreateLabelMap()
93+
{
94+
var container = new JsonObject();
95+
foreach (var label in labels)
96+
{
97+
container.Add(label.name, label.value);
98+
}
99+
return container;
100+
}
101+
102+
static JsonArray ToJsonArray(string[] items) => new JsonArray(items.Where(s => !string.IsNullOrEmpty(s)).Select(s => (JsonValue)s).ToArray());
65103

66104
public void SetEntrypoint(string[] executableArgs, string[]? args = null)
67105
{
@@ -86,14 +124,23 @@ public void SetEntrypoint(string[] executableArgs, string[]? args = null)
86124
RecalculateDigest();
87125
}
88126

89-
public string WorkingDirectory {
90-
get => (string?)manifest["config"]!["WorkingDir"] ?? "";
91-
set {
127+
public string WorkingDirectory
128+
{
129+
get => (string?)config["config"]!["WorkingDir"] ?? "";
130+
set
131+
{
92132
config["config"]!["WorkingDir"] = value;
93133
RecalculateDigest();
94134
}
95135
}
96136

137+
public void Label(string name, string value)
138+
{
139+
labels.Add(new(name, value));
140+
config["config"]!["Labels"] = CreateLabelMap();
141+
RecalculateDigest();
142+
}
143+
97144
public string GetDigest(JsonNode json)
98145
{
99146
string hashString;

Microsoft.NET.Build.Containers/build/Microsoft.NET.Build.Containers.targets

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,20 @@
2525
<ContainerWorkingDirectory Condition="'$(ContainerWorkingDirectory)' == ''">/app</ContainerWorkingDirectory>
2626
<!-- Could be semicolon-delimited -->
2727
</PropertyGroup>
28-
29-
<ItemGroup>
30-
<ContainerLabel Condition="@(ContainerLabel) == ''"></ContainerLabel>
28+
29+
<ItemGroup Label="Entrypoint Assignment">
3130
<!-- For non-apphosts, we need to invoke `dotnet` `workingdir/app` as separate args -->
3231
<ContainerEntrypoint Condition="'$(ContainerEntrypoint)' == '' and '$(UseAppHost)' != 'true'" Include="dotnet;$(ContainerWorkingDirectory)/$(TargetFileName)" />
3332
<!-- For apphosts, we need to invoke `workingdir/app` as a single arg -->
3433
<ContainerEntrypoint Condition="'$(ContainerEntrypoint)' == '' and '$(UseAppHost)' == 'true'" Include="$(ContainerWorkingDirectory)/$(AssemblyName)$(_NativeExecutableExtension)" />
3534
</ItemGroup>
3635

36+
<ItemGroup Label="Conventional Label assignment">
37+
<ContainerLabel Include="org.opencontainers.image.created" Value="$([System.DateTime]::UtcNow.ToString('o'))" />
38+
</ItemGroup>
39+
3740
<!-- Asp.NET defaults -->
38-
<ItemGroup Condition="'$(_IsAspNet)' == 'true'">
41+
<ItemGroup Label="ASP.NET port forwarding" Condition="'$(_IsAspNet)' == 'true'">
3942
<ContainerPort Include="80" Type="tcp" Condition="@(ContainerPort->WithMetadataValue('Identity', '80')->AnyHaveMetadataValue('Type', 'tcp')) == ''" />
4043

4144
<ContainerEnvironmentVariable Include="ASPNETCORE_URLS" Value="http://localhost:5000;https://localhost:5001"
@@ -72,6 +75,7 @@
7275
PublishDirectory="$(PublishDir)"
7376
WorkingDirectory="$(ContainerWorkingDirectory)"
7477
Entrypoint="@(ContainerEntrypoint)"
75-
EntrypointArgs="@(ContainerEntrypointArgs)"/>
78+
EntrypointArgs="@(ContainerEntrypointArgs)"
79+
Labels="@(ContainerLabel)"/>
7680
</Target>
7781
</Project>

0 commit comments

Comments
 (0)