Il peut arriver, que vous ayez besoin de retrouver le code d’une azure function déployée sur Azure alors que celle-ci a été déployée en mode compilée depuis Visual Studio.
(Bon ok j’ai oublié de commit et plus tard …. mon collègue Matthieu m’a demandé de redeployer mon code… qui n’existait plus nulle part 🙁 )
Tout n’est pas perdu, voici quelques étape pour retrouver notre code.
1 – Récupérer le code depuis la Function Apps
Pour ce faire, commençons par comprendre où se situe le code en question, celui-ci est compilé et déployé sur le service au chemin indiqué dans l’écran Integrate de la fonction.
Il va donc falloir accéder à cette DLL qui contient le précieux code, il existe plusieurs méthodes pour le faire (SFTP / VISUAL Studio…) mais j’aime bien la simplicité proposée par l’outil en ligne Kudu accessible depuis l’onglet platform de l’application.
Ensuite depuis CMD il va être possible de récupérer le fichier.
Le téléchargement est réalisable directement dans le dossier indiqué dans l’écran Integrate.
La DLL récupérée sur notre poste, il est nécessaire de la décompiler, pour cela je vous recommande l’excellent JetBrains dotPeek qui est gratuit et qui va permettre d’obtenir le code MSIL de notre DLL, ce n’est pas exactement le code que nous avions déployé mais avec un peu de nettoyage cela va le devenir.
On ouvre la DLL avec celui-ci :
Le code MSIL obtenu est le suivant :
[FunctionName("list-tables")]
public static async Task<HttpResponseMessage> ListTables(
[HttpTrigger(AuthorizationLevel.Function, new string[] {"get"}, Route = "ssas-list-tables/{region}/{servername}/{database}")] HttpRequestMessage req,
ILogger log,
string region,
string servername,
string database)
{
try
{
string str = "Provider=MSOLAP;Data Source=asazure://" + region + ".asazure.windows.net/" + servername + ";User ID=;Password={0};Persist Security Info=True;Impersonation Level=Impersonate";
IFormatProvider provider = (IFormatProvider) CultureInfo.InvariantCulture;
string format = str;
string connectionString = string.Format(provider, format, (object) await SSASUtils.GetAccessTokenAsync("https://*.asazure.windows.net"));
provider = (IFormatProvider) null;
format = (string) null;
Microsoft.AnalysisServices.Server server = new Microsoft.AnalysisServices.Server();
server.Connect(connectionString);
return HttpRequestMessageExtensions.CreateResponse<IEnumerable<string>>(req, HttpStatusCode.OK, (M0) server.Databases.FindByName(database).Model.Tables.Select<Table, string>((Func<Table, string>) (x => x.Name)));
}
catch (Exception ex)
{
return HttpRequestMessageExtensions.CreateResponse<string>(req, HttpStatusCode.InternalServerError, (M0) ex.Message);
}
}
Après nettoyage :
[FunctionName("list-tables")]
public static async Task<HttpResponseMessage> ListTables(
[HttpTrigger(AuthorizationLevel.Function, "get" , Route = "ssas-list-tables/{region}/{servername}/{database}")] HttpRequestMessage req,
ILogger log,
string region,
string servername,
string database)
{
try
{
string str = "Provider=MSOLAP;Data Source=asazure://" + region + ".asazure.windows.net/" + servername + ";User ID=;Password={0};Persist Security Info=True;Impersonation Level=Impersonate";
IFormatProvider provider = CultureInfo.InvariantCulture;
string format = str;
string connectionString = string.Format(provider, format, await SSASUtils.GetAccessTokenAsync("https://*.asazure.windows.net"));
provider =null;
format = null;
Microsoft.AnalysisServices.Server server = new Microsoft.AnalysisServices.Server();
server.Connect(connectionString);
return req.CreateResponse(HttpStatusCode.OK, server.Databases.FindByName(database).Model.Tables.Select(x => x.Name));
}
catch (Exception ex)
{
return req.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
}
}
Et voilà on peut versionner notre code disparu, et l’opération n’aura pas pris plus de 10 minutes.