Skip to content

Commit 17a6178

Browse files
authored
ACR Integration: Add JSON metadata to package manifest in ACR registries (#1522)
1 parent f6a4ab9 commit 17a6178

File tree

2 files changed

+79
-40
lines changed

2 files changed

+79
-40
lines changed

src/code/ACRServerAPICalls.cs

Lines changed: 77 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,6 @@ private Stream InstallVersion(
603603
{
604604
return null;
605605
}
606-
607606
string digest = GetDigestFromManifest(manifest, out errRecord);
608607
if (errRecord != null)
609608
{
@@ -1018,7 +1017,7 @@ private static Collection<KeyValuePair<string, string>> GetDefaultHeaders(string
10181017
};
10191018
}
10201019

1021-
internal bool PushNupkgACR(string outputNupkgDir, string pkgName, NuGetVersion pkgVersion, PSRepositoryInfo repository, out ErrorRecord errRecord)
1020+
internal bool PushNupkgACR(string psd1OrPs1File, string outputNupkgDir, string pkgName, NuGetVersion pkgVersion, PSRepositoryInfo repository, Hashtable parsedMetadataHash, out ErrorRecord errRecord)
10221021
{
10231022
errRecord = null;
10241023
// Push the nupkg to the appropriate repository
@@ -1050,42 +1049,19 @@ internal bool PushNupkgACR(string outputNupkgDir, string pkgName, NuGetVersion p
10501049
_cmdletPassedIn.WriteVerbose("Getting acr access token");
10511050
var acrAccessToken = GetAcrAccessToken(registry, acrRefreshToken, out errRecord);
10521051

1052+
/* Uploading .nupkg */
10531053
_cmdletPassedIn.WriteVerbose("Start uploading blob");
10541054
var moduleLocation = GetStartUploadBlobLocation(registry, pkgName, acrAccessToken).Result;
10551055

10561056
_cmdletPassedIn.WriteVerbose("Computing digest for .nupkg file");
1057-
bool digestCreated = CreateDigest(fullNupkgFile, out string digest, out ErrorRecord digestError);
1058-
if (!digestCreated)
1057+
bool nupkgDigestCreated = CreateDigest(fullNupkgFile, out string nupkgDigest, out ErrorRecord nupkgDigestError);
1058+
if (!nupkgDigestCreated)
10591059
{
1060-
_cmdletPassedIn.ThrowTerminatingError(digestError);
1060+
_cmdletPassedIn.ThrowTerminatingError(nupkgDigestError);
10611061
}
10621062

10631063
_cmdletPassedIn.WriteVerbose("Finish uploading blob");
1064-
bool moduleUploadSuccess = EndUploadBlob(registry, moduleLocation, fullNupkgFile, digest, false, acrAccessToken).Result;
1065-
1066-
_cmdletPassedIn.WriteVerbose("Create an empty file");
1067-
string emptyFileName = "empty.txt";
1068-
var emptyFilePath = System.IO.Path.Combine(outputNupkgDir, emptyFileName);
1069-
// Rename the empty file in case such a file already exists in the temp folder (although highly unlikely)
1070-
while (File.Exists(emptyFilePath))
1071-
{
1072-
emptyFilePath = Guid.NewGuid().ToString() + ".txt";
1073-
}
1074-
FileStream emptyStream = File.Create(emptyFilePath);
1075-
emptyStream.Close();
1076-
1077-
_cmdletPassedIn.WriteVerbose("Start uploading an empty file");
1078-
var emptyLocation = GetStartUploadBlobLocation(registry, pkgName, acrAccessToken).Result;
1079-
1080-
_cmdletPassedIn.WriteVerbose("Computing digest for empty file");
1081-
bool emptyDigestCreated = CreateDigest(emptyFilePath, out string emptyDigest, out ErrorRecord emptyDigestError);
1082-
if (!emptyDigestCreated)
1083-
{
1084-
_cmdletPassedIn.ThrowTerminatingError(emptyDigestError);
1085-
}
1086-
1087-
_cmdletPassedIn.WriteVerbose("Finish uploading empty file");
1088-
bool emptyFileUploadSuccess = EndUploadBlob(registry, emptyLocation, emptyFilePath, emptyDigest, false, acrAccessToken).Result;
1064+
bool moduleUploadSuccess = EndUploadBlob(registry, moduleLocation, fullNupkgFile, nupkgDigest, false, acrAccessToken).Result;
10891065

10901066
_cmdletPassedIn.WriteVerbose("Create the config file");
10911067
string configFileName = "config.json";
@@ -1096,11 +1072,25 @@ internal bool PushNupkgACR(string outputNupkgDir, string pkgName, NuGetVersion p
10961072
}
10971073
FileStream configStream = File.Create(configFilePath);
10981074
configStream.Close();
1075+
_cmdletPassedIn.WriteVerbose("Computing digest for config");
1076+
bool configDigestCreated = CreateDigest(configFilePath, out string configDigest, out ErrorRecord configDigestError);
1077+
if (!configDigestCreated)
1078+
{
1079+
_cmdletPassedIn.ThrowTerminatingError(configDigestError);
1080+
}
1081+
1082+
/* Create manifest layer */
1083+
_cmdletPassedIn.WriteVerbose("Create package version metadata as JSON string");
1084+
string jsonString = CreateMetadataContent(psd1OrPs1File, parsedMetadataHash, out ErrorRecord metadataCreationError);
1085+
if (metadataCreationError != null)
1086+
{
1087+
_cmdletPassedIn.ThrowTerminatingError(metadataCreationError);
1088+
}
10991089

11001090
FileInfo nupkgFile = new FileInfo(fullNupkgFile);
11011091
var fileSize = nupkgFile.Length;
11021092
var fileName = System.IO.Path.GetFileName(fullNupkgFile);
1103-
string fileContent = CreateJsonContent(digest, emptyDigest, fileSize, fileName);
1093+
string fileContent = CreateJsonContent(nupkgDigest, configDigest, fileSize, fileName, jsonString);
11041094
File.WriteAllText(configFilePath, fileContent);
11051095

11061096
_cmdletPassedIn.WriteVerbose("Create the manifest layer");
@@ -1113,7 +1103,12 @@ internal bool PushNupkgACR(string outputNupkgDir, string pkgName, NuGetVersion p
11131103
return false;
11141104
}
11151105

1116-
private string CreateJsonContent(string digest, string emptyDigest, long fileSize, string fileName)
1106+
private string CreateJsonContent(
1107+
string nupkgDigest,
1108+
string configDigest,
1109+
long nupkgFileSize,
1110+
string fileName,
1111+
string jsonString)
11171112
{
11181113
StringBuilder stringBuilder = new StringBuilder();
11191114
StringWriter stringWriter = new StringWriter(stringBuilder);
@@ -1131,31 +1126,31 @@ private string CreateJsonContent(string digest, string emptyDigest, long fileSiz
11311126
jsonWriter.WritePropertyName("mediaType");
11321127
jsonWriter.WriteValue("application/vnd.unknown.config.v1+json");
11331128
jsonWriter.WritePropertyName("digest");
1134-
jsonWriter.WriteValue($"sha256:{emptyDigest}");
1129+
jsonWriter.WriteValue($"sha256:{configDigest}");
11351130
jsonWriter.WritePropertyName("size");
11361131
jsonWriter.WriteValue(0);
11371132
jsonWriter.WriteEndObject();
11381133

11391134
jsonWriter.WritePropertyName("layers");
11401135
jsonWriter.WriteStartArray();
1141-
jsonWriter.WriteStartObject();
11421136

1137+
jsonWriter.WriteStartObject();
11431138
jsonWriter.WritePropertyName("mediaType");
11441139
jsonWriter.WriteValue("application/vnd.oci.image.layer.nondistributable.v1.tar+gzip'");
11451140
jsonWriter.WritePropertyName("digest");
1146-
jsonWriter.WriteValue($"sha256:{digest}");
1141+
jsonWriter.WriteValue($"sha256:{nupkgDigest}");
11471142
jsonWriter.WritePropertyName("size");
1148-
jsonWriter.WriteValue(fileSize);
1143+
jsonWriter.WriteValue(nupkgFileSize);
11491144
jsonWriter.WritePropertyName("annotations");
1150-
11511145
jsonWriter.WriteStartObject();
11521146
jsonWriter.WritePropertyName("org.opencontainers.image.title");
11531147
jsonWriter.WriteValue(fileName);
1148+
jsonWriter.WritePropertyName("metadata");
1149+
jsonWriter.WriteValue(jsonString);
11541150
jsonWriter.WriteEndObject();
1155-
11561151
jsonWriter.WriteEndObject();
1157-
jsonWriter.WriteEndArray();
11581152

1153+
jsonWriter.WriteEndArray();
11591154
jsonWriter.WriteEndObject();
11601155

11611156
return stringWriter.ToString();
@@ -1205,6 +1200,49 @@ private bool CreateDigest(string fileName, out string digest, out ErrorRecord er
12051200
return true;
12061201
}
12071202

1203+
private string CreateMetadataContent(string manifestFilePath, Hashtable parsedMetadata, out ErrorRecord metadataCreationError)
1204+
{
1205+
metadataCreationError = null;
1206+
Hashtable parsedMetadataHash = null;
1207+
string jsonString = string.Empty;
1208+
1209+
// A script will already have the metadata parsed into the parsedMetadatahash,
1210+
// a module will still need the module manifest to be parsed.
1211+
if (parsedMetadata == null || parsedMetadata.Count == 0)
1212+
{
1213+
// Use the parsed module manifest data as 'parsedMetadataHash' instead of the passed-in data.
1214+
if (!Utils.TryReadManifestFile(
1215+
manifestFilePath: manifestFilePath,
1216+
manifestInfo: out parsedMetadataHash,
1217+
error: out Exception manifestReadError))
1218+
{
1219+
metadataCreationError = new ErrorRecord(
1220+
manifestReadError,
1221+
"ManifestFileReadParseForACRPublishError",
1222+
ErrorCategory.ReadError,
1223+
_cmdletPassedIn);
1224+
1225+
return jsonString;
1226+
}
1227+
}
1228+
1229+
if (parsedMetadataHash == null)
1230+
{
1231+
metadataCreationError = new ErrorRecord(
1232+
new InvalidOperationException("Error parsing package metadata into hashtable."),
1233+
"PackageMetadataHashEmptyError",
1234+
ErrorCategory.InvalidData,
1235+
_cmdletPassedIn);
1236+
1237+
return jsonString;
1238+
}
1239+
1240+
_cmdletPassedIn.WriteVerbose("Serialize JSON into string.");
1241+
jsonString = System.Text.Json.JsonSerializer.Serialize(parsedMetadataHash);
1242+
1243+
return jsonString;
1244+
}
1245+
12081246
#endregion
12091247
}
12101248
}

src/code/PublishPSResource.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,8 @@ out string[] _
486486
{
487487
ACRServerAPICalls acrServer = new ACRServerAPICalls(repository, this, _networkCredential, userAgentString);
488488

489-
if (!acrServer.PushNupkgACR(outputNupkgDir, _pkgName.ToLower(), _pkgVersion, repository, out ErrorRecord pushNupkgACRError))
489+
var pkgMetadataFile = (resourceType == ResourceType.Script) ? pathToScriptFileToPublish : pathToModuleManifestToPublish;
490+
if (!acrServer.PushNupkgACR(pkgMetadataFile, outputNupkgDir, _pkgName, _pkgVersion, repository, parsedMetadata, out ErrorRecord pushNupkgACRError))
490491
{
491492
WriteError(pushNupkgACRError);
492493
// exit out of processing

0 commit comments

Comments
 (0)