Tips : Création de différents Load Balancers via des templates ARM

FÉVR23

Voici un nouvel article sur la création de ressources Azure en ARM, ici il va s’agir du Load Balancer, tout ceux qui en ont créé un via le portail Azure, savent qu’il s’agit d’une bonne heure de clic-o-drome.

Cette fois ci, on va corser la chose, je vais vous montrer comment créer :

  • Plusieurs load balancers
  • Privé ou publique
  • Plusieurs ports ouverts

On va donc partir sur ce jeu de paramètres :

"loadBalancers": {
   "value": [
     {
       "name": "front",
       "accessType": "public",
       "dns": "wwosfdemo",
       "port": [ 80, 8080, 443 ]
     },
     {
       "name": "middle",
       "accessType": "private",
       "subnetName": "MiddleSubnet",
       "port": [ 8081 ]
     },
     {
       "name": "back",
       "accessType": "private",
       "subnetName": "BackSubnet",
       "port": [ 8082 ]
     },
     {
       "name": "admin",
       "accessType": "private",
       "subnetName": "AdminSubnet",
       "port": [ 19000, 19080 ]
     }

   ]
}

Pour ceux qui l’ont reconnu, ça ressemble beaucoup à un use case complexe d’une architecture Service Fabric.

Pour créer ces différentes ressources, j’ai donc besoin de 3 types de ressources qui sont :

  • Public IP : pour pouvoir exposer mes External Load Balancer
  • Subnet (et donc Virtual Network) : pour pouvoir conserver mes Internal Load Balancers
  • Load Balancer : pour créer mes Internal et External Load Balancer

Je sépare les uses case “privés” et “publique” pour des questions de lisibilité, sachant qu’on a déjà des boucles imbriquées dans ce template, on ne va pas complexifier la chose encore une fois.

Pour la création des Virtual Network je vous renvoie à mon précédent article qui parle de ce sujet là : http://blog.woivre.fr/blog/2017/12/tips-creation-dazure-virtual-network-via-les-templates-arm #autopromo

Pour la création des adresses IP publiques, on va utiliser cette partie de template :

{
   "apiVersion": "2017-10-01",
   "type": "Microsoft.Network/publicIPAddresses",
   "condition": "[equals(variables('loadBalancers')[copyIndex('publicIpLoop')].accessType, 'public')]",
   "name": "[concat(variables('loadBalancers')[copyIndex('publicIpLoop')].name, variables('suffix').publicIPAddress)]",
   "location": "[resourceGroup().location]",
   "tags": {
     "displayName": "Public IP"
   },
   "properties": {
     "dnsSettings": {
       "domainNameLabel": "[variables('loadBalancers')[copyIndex('publicIpLoop')].dns]"
     },
     "publicIPAllocationMethod": "Dynamic"
   },
   "copy": {
     "name": "publicIpLoop",
     "count": "[length(variables('loadBalancers'))]"
   }
}

On fait donc ici un mixte entre une boucle et une condition pour créer une adresse IP publique pour chacun de nos Load balancer qui en a besoin. Par ailleurs je vous conseille de nommer vos différentes boucles dans un template ARM pour des questions de lisibilité encore une fois.

Pour les Load Balancers, rappelons rapidement la structure d’un Load Balancer qui est au minima la suivante :

{
   "apiVersion": "2017-10-01",
   "type": "Microsoft.Network/loadBalancers",
   "name": "LoadBalancer",
   "location": "[resourceGroup().location]",
   "properties": {
     "frontendIPConfigurations": [],
     "backendAddressPools": [],
     "inboundNatPools": [],
     "probes": [],
     "loadBalancingRules": []
   }
}

Commençons donc par les Load Balancers publiques :

{
   "apiVersion": "2017-10-01",
   "type": "Microsoft.Network/loadBalancers",
   "condition": "[equals(variables('loadBalancers')[copyIndex('loadBalancersLoop')].accessType, 'public')]",
   "name": "[concat(variables('loadBalancers')[copyIndex('loadBalancersLoop')].name, variables('suffix').publicLoadBalancers)]",
   "location": "[resourceGroup().location]",
   "tags": {
     "displayName": "External Load Balancer"
   },
   "dependsOn": [
     "publicIpLoop"
   ],
   "properties": {
     "frontendIPConfigurations": [
       {
         "name": "FrontEndPublicIPConfiguration",
         "properties": {
           "publicIPAddress": {
             "id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('loadBalancers')[copyIndex('loadBalancersLoop')].name, variables('suffix').publicIPAddress))]"
           }
         }
       }
     ],
     "backendAddressPools": [
       {
         "name": "BackEndAddressPool"
       }
     ],
     "inboundNatPools": [
       {
         "name": "BackEndNatPool",
         "properties": {
           "backendPort": 3389,
           "frontendIPConfiguration": {
             "id": "[concat(resourceId('Microsoft.Network/loadBalancers', concat(variables('loadBalancers')[copyIndex('loadBalancersLoop')].name, variables('suffix').publicLoadBalancers)), '/frontendIPConfigurations/FrontEndPublicIPConfiguration')]"
           },
           "frontendPortRangeEnd": 4500,
           "frontendPortRangeStart": 3389,
           "protocol": "Tcp"
         }
       }
     ],
     "copy": [
       {
         "name": "probes",
         "count": "[length(variables('loadBalancers')[copyIndex('loadBalancersLoop')].port)]",
         "input": {
           "name": "[concat('probe-', variables('loadBalancers')[copyIndex('loadBalancersLoop')].port[copyIndex('probes')])]",
           "properties": {
             "intervalInSeconds": 5,
             "numberOfProbes": 2,
             "port": "[variables('loadBalancers')[copyIndex('loadBalancersLoop')].port[copyIndex('probes')]]",
             "protocol": "Tcp"
           }
         }
       },
       {
         "name": "loadBalancingRules",
         "count": "[length(variables('loadBalancers')[copyIndex('loadBalancersLoop')].port)]",
         "input": {
           "name": "[concat('rule-', variables('loadBalancers')[copyIndex('loadBalancersLoop')].port[copyIndex('loadBalancingRules')])]",
           "properties": {
             "backendAddressPool": {
               "id": "[concat(resourceId('Microsoft.Network/loadBalancers', concat(variables('loadBalancers')[copyIndex('loadBalancersLoop')].name, variables('suffix').publicLoadBalancers)), '/backendAddressPools/BackEndAddressPool')]"
             },
             "backendPort": "[variables('loadBalancers')[copyIndex('loadBalancersLoop')].port[copyIndex('loadBalancingRules')]]",
             "enableFloatingIP": false,
             "frontendIPConfiguration": {
               "id": "[concat(resourceId('Microsoft.Network/loadBalancers', concat(variables('loadBalancers')[copyIndex('loadBalancersLoop')].name, variables('suffix').publicLoadBalancers)), '/frontendIPConfigurations/FrontEndPublicIPConfiguration')]"
             },
             "frontendPort": "[variables('loadBalancers')[copyIndex('loadBalancersLoop')].port[copyIndex('loadBalancingRules')]]",
             "idleTimeoutInMinutes": 5,
             "probe": {
               "id": "[concat(resourceId('Microsoft.Network/loadBalancers', concat(variables('loadBalancers')[copyIndex('loadBalancersLoop')].name, variables('suffix').publicLoadBalancers)), '/probes/', concat('probe-', variables('loadBalancers')[copyIndex('loadBalancersLoop')].port[copyIndex('loadBalancingRules')]))]"
             },
             "protocol": "Tcp"
           }
         }
       }
     ]
   },
   "copy": {
     "name": "loadBalancersLoop",
     "count": "[length(variables('loadBalancers'))]"
   }
}

On peut voir que c’est un peu verbeux puisque j’ai une boucle sur les Load Balancer, ainsi qu’une boucle sur les différents ports de chacun. Par ailleurs étant donné le fait que la partie “rules” contient uniquement des id de ressource, c’est juste un jeu de construction de template. Le tout se construit plutôt bien si vous êtes assez concentrés lors de l’écriture de celui-ci.


Pour les Load balancers privés, on repart sur le même template sauf pour les conditions, et la gestion de la FrontEndIpConfiguration qui indique un sous réseau, plutôt qu’une adresse IP Publique, comme on peut le voir ci-dessous :

"frontendIPConfigurations": [
   {
     "name": "FrontEndPrivateIPConfiguration",
     "properties": {
       "subnet": {
         "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetwork').name), '/subnets/', variables('loadBalancers')[copyIndex('loadBalancersLoop')].subnetName)]"
       }
     }
   }

Le template est présent dans cet article, je ne le mets pas de suite sur Github, je vous le mettrai avec un article prochain sur la création d’un cluster Service Fabric complexe via un template ARM.


Remonter

Bonne résolution : Prendre soin de son cluster Service Fabric

JANV23

Pour ceux qui ne connaissent pas Service Fabric, il s’agit d’un produit fourni par Microsoft qui permet de mettre en place des architectures micro-services basées soit sur des “Guest Exe”, des containers ou des “reliable service” qui sont dans ce cas présent, des applications développées avec un SDK fourni par l’éditeur.


Ceux qui ont déjà testé Service Fabric dans un cadre projet ont pu voir qu’il est assez magique et rapide de mettre en place des solutions qui fonctionnent toutes seules. Par toutes seules, je veux bien entendu parler de toutes les fonctionnalités “automagiques” qu’offre Service Fabric, comme la répartition automatique des micro-services au sein du cluster, l’auto-healing du cluster, ou encore la gestion des données des différents services stateful.


Maintenant rien n’est vraiment magique si on creuse vraiment comment cela marche, mais ce n’est pas le but de cet article, nous allons voir comment faire en sorte de bien prendre soin de son cluster pour qu’il n’arrive rien d’irrémédiable à celui-ci. Et quand je veux dire rien d’irrémédiable, je parle du moment où vous vous dîtes : “Autant créer un nouveau cluster et rattraper mes données, car l’actuel est bon pour la casse”, bon après vous me direz que cette méthode marche et elle a souvent été éprouvée, mais bon ça n’arrive jamais au bon moment.


Laissez lui de l’air pour que votre cluster s’épanouisse :

A part le fait que cette phrase marche aussi avec un adolescent, il est nécessaire de laisser de l’espace disque sur les différents nœuds de votre cluster pour qu’il puisse effectuer ses opérations sans aucun soucis. Alors grand scoop, Service Fabric a beau être présenté comme du PaaS sur Azure, derrière, vous allez monter un cluster de Virtual Machine Scale Set (moi j’appelle ça du IaaS), le côté PaaS offert par Azure sur votre cluster SF concerne surtout les updates des versions de Service Fabric, les autres fonctionnalités qui sont présentées avec le produit sont les mêmes pour un cluster on premise ou créer à la main sur des Virtual Machine Azure ou AWS ou autre ... Donc ce cluster Scale Set, il faut le bichonner c’est grâce à lui que votre Service Fabric fonctionne, un des éléments à prendre en compte c’est l’espace disque disponible pour vos applications.

Bon vous me direz un disque dur ça ne se remplit pas tout seul, et bien je suis d’accord, tout dépend de votre utilisation de votre cluster. Si on exclu les erreurs courantes d’occupation d’espace disque, comme la génération de fichiers de logs sur le disque local sans mettre en place de politique de purge. Service Fabric peut utiliser l’espace disque pour stocker l’état des services stateful que ce soit vos acteurs ou vos “reliable service”, donc si vous ne supprimez jamais les données locales, il est possible de ne plus avoir d’espace disque si vous avez des acteurs qui gèrent beaucoup de données en disque.

Pour éviter ce problème, il est possible de faire les actions suivantes :

- Supprimer vos acteurs qui ne sont plus utilisés, par exemple ceux qui font des actions temporaires dans un traitement

- Mettre en place une politique de stockage à double niveau, à la fois basée sur le cluster, puis un déchargement sur un Blob Storage (ou autre).

- Mettre en place des alertes sur l’espace disque utilisé afin d’éviter les mauvaises surprises le jour où cela pose problème.


Les disques à monitorer dépendent de l’installation de votre cluster, si vous êtes passé par un template ARM comme celui disponible sur le GitHub de Microsoft (https://github.com/Azure/azure-quickstart-templates/blob/master/service-fabric-secure-cluster-5-node-1-nodetype/azuredeploy.json), vous pouvez voir qu’il y a une propriété nodeDataDrive qui vous permet de positionner les données de votre cluster sur le disque OS ou sur le disque Temp. A noter qu’il est possible de mettre vos données sur le disque Temp sans risque majeur si vos applications sont bien conçues elles sont redondées sur différents nœuds du cluster.


Dans l’hypothèse ou il est trop tard, et que votre cluster est chargé de beaucoup de données, il est parfois possible de supprimer des applications via les API Service Fabric. Cependant, cette opération ne marche pas toujours si votre cluster est vraiment plein. La dernière chance est souvent celle de se connecter au cluster via RDP (ou SSH si c’est un cluster Linux) et de supprimer les dossiers contenant les données liées à la persistance de vos services. J’espère par ailleurs que vous n’arriverez pas à cette solution ultime et brutale.


Les clusters adoptent une démarche démocratique :

Si vous vous êtes intéressé un peu à la notion de cluster, notamment celui de Service Fabric, vous devez savoir qu’il y des nœuds et des composants qu’on ne peut pas supprimer sans y prendre une attention toute particulière. Au sein de Service Fabric, il y a une notion de “Seed Node” que ce soit on-premise ou sur Azure, ces nœuds particuliers hébergent entre autre les applications systèmes servant au bon fonctionnement du cluster, il est donc fortement conseillé de faire en sorte que ces nœuds soient toujours opérationnels. Vous allez me dire que vu que c’est du Service Fabric managé, et que c’est automagique, vous n’avez rien à craindre pour ces nœuds. Et bien non, ce n’est pas le cas, derrière votre cluster il y a un cluster de Virtual Machine Scale Set, et la mauvaise nouvelle c’est que vous y avez accès, donc c’est à vous de le manager et de s’assurer qu’il se porte bien. Vous pouvez voir la liste de vos “Seed Node” dans le cluster manifest, comme on peut le voir ci dessous :

image


A noter que le XML de déclaration de l’infrastructure change entre un cluster “on premise” et un cluster Azure. De même selon le niveau de durabilité de votre cluster, le nombre de vos seed nodes est différents.


Alors je parle de démocratie, puisque toute opération d’infrastructure doit être votée par l’ensemble du chorum que forme l’ensemble de ses Seed Nodes. Un cas concret, si par exemple vous avez perdu un de vos seeds node, et que vous souhaitez mettre à jour votre cluster, celle-ci ne se fera pas.


Alors ce cas là arrive uniquement quand vous faites les opérations suivantes :

- Supprimer un nœud de votre cluster ScaleSet (oui la ressource n’est pas verrouillée par Service Fabric)

- Scale Up / Scale down, il est possible que les nœuds du chorum soient supprimés

- Créer votre cluster Scale Set avec le paramètre overProvision à true, dans ce cas précis lors de la création il crée plus de serveurs que nécessaire, et après il supprime ceux qu’il juge en trop, donc peut être vos nœuds de chorum

- Maltraiter les fichiers Service Fabric situés sur votre cluster, bon là ça devient intentionnel....


Si par hasard, c’est trop tard et que vos “Seed Nodes” sont cassés, vous pouvez envoyer un mail au support Microsoft Azure qui vous dira quasiment à chaque fois qu’il faut recréer votre cluster, ce qui peut être problématique dans le cas où vous vous êtes basé sur un cluster appartenant à un Virtual Network un peu petit et ayant des contraintes d’adressage IP, comme pour un cluster privé.


Pour éviter cela, c’est très simple, il suffit soit de faire grandement attention lorsque vous touchez l’infrastructure sous jacente à votre cluster. Il est possible de totalement protéger votre cluster Scale Set Service Fabric si vous prenez la peine de créer 2 types de nœuds lors de la création de votre cluster, le premier type contiendra les services “systèmes” et le deuxième vos services applicatifs, il faudra bien entendu prendre ceci en compte lors de vos déploiements.


Via le portail Azure, lorsque vous créer votre cluster, vous pouvez faire comme cela :


image


Il est bien entendu possible de faire tout cela en ARM (car après tout qui déploie des ressources Azure depuis le portail Azure ....) Bref à la création, vous aurez 2 clusters Scale Set, à vous de mettre des droits restreints sur le scale set sysnode dans mon cas, et pour preuve :


image

Si vous creusez un peu plus le cluster, vous pourrez voir que les applications systèmes sont toutes dans le scale set “sysnode” à l’exception du DnsService qui est présent sur tous les nœuds.


Bref prenez soin de vos clusters avant que les problèmes surviennent, car ils n’arrivent jamais au bon moment et les résolutions sont soit pas simples à mettre en œuvre, soit assez destructives pour le cluster.


Remonter

Tips : Création d’Azure Virtual Network via les templates ARM

DÉCE22


Il existe de multiples manières de créer des ressources sur la plateforme Azure, je ne dirais pas qu’il y en a de meilleures que d’autres, elles ont chacune leurs avantages et leurs inconvénients. Pour rappel, pour créer des ressources sur Azure, vous avez la possibilité de le faire d’une des manières suivantes :

  • Via le portail Azure qui a le mérite d’être simple à utiliser et correspond très bien au besoin si vous souhaitez mettre en place une ressource Azure pour la première fois, ou pour créer une ressource à des vues de tests. Par contre, c’est peu automatisable, et je ne conseille pas de se dire “hey si je faisais ma création de ressources via un test ui automatisé”
  • Via la CLI ou du powershell qui ont le mérite de pouvoir être jouer de manière automatisée et qui permettent de créer rapidement des ressources via du code, cependant il va falloir prendre en compte les comportements lorsqu’une ressource existe déjà. Et bien entendu la méthode “je supprime si la ressource existe” puis je recrée a quelques limites.
  • Via les REST API Azure sont certes très puissantes, mais il y a du code à écrire, à maintenir, et on retrouve les mêmes désavantages qu’avec une ligne de commande.
  • Via des templates ARM qui sont en réalité une surcouche aux REST API Azure vont vous permettre de décrire votre architecture via un “simple” modèle JSON. Par ailleurs, ils gèrent nativement les ressources existantes en apportant les modifications si besoin, donc pas de soucis à se faire là dessus. Cependant ces templates sont plutôt verbeux, ce qui ne facilite pas toujours leur adoption, de plus ils ont quelques limites que nous ne verrons pas dans cet article.


Si je prends comme exemple la création d’un Virtual Network, si je veux le créer via un template ARM, soit j’exporte un template ARM depuis un VNET existant sur Azure, soit je pars d’une feuille blanche, soit je vais voir ce magnifique repo GIT de Microsoft : https://github.com/Azure/azure-quickstart-templates. Il a pour avantage de contenir toute sorte de template pour à peu près toutes les ressources Azure disponible.

Après avoir trouvé le template que je souhaite, je peux le prendre et m’en inspirer pour faire un template avec mes paramètres souhaités et divers autres changements, je vais donc avoir quelque chose de ce type :

{
     "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
     "contentVersion": "1.0.0.0",
     "parameters": {
         "vnetName": {
             "type":"string",
             "defaultValue": "demo-vnet",
             "metadata": {
                 "description" : "Virtual network name"
             }
         },
         "vnetAddressPrefix": {
             "type": "string",
             "defaultValue": "16.0.0.0/16",
             "metadata": {
                 "description": "Address prefix"
             }
         },
         "subnet1Name": {
             "type": "string",
             "defaultValue": "Front",
             "metadata": {
                 "description": "Subnet name"               
             }
         },
         "subnet1Prefix": {
             "type": "string",
             "defaultValue": "16.0.1.0/24",
             "metadata": {
                 "description": "subnet 1 prefix"
             }
         },
         "subnet2Name": {
             "type": "string",
             "defaultValue": "Back",
             "metadata": {
                 "description": "Subnet name"               
             }
         },
         "subnet2Prefix": {
             "type": "string",
             "defaultValue": "16.0.3.0/24",
             "metadata": {
                 "description": "subnet 2 prefix"
             }
         }
     },
     "variables": {
         "vnetName":"[parameters('vnetName')]",
         "vnetAddressPrefix": "[parameters('vnetAddressPrefix')]",
         "subnet1Name": "[parameters('subnet1Name')]",
         "subnet1Prefix": "[parameters('subnet1Prefix')]",
         "subnet2Name": "[parameters('subnet2Name')]",
         "subnet2Prefix": "[parameters('subnet2Prefix')]"
     },
     "resources": [
         {
             "apiVersion": "2015-06-15",
             "type": "Microsoft.Network/virtualNetworks",
             "name": "[variables('vnetName')]",
             "location": "[resourceGroup().location]",
             "properties": {
               "addressSpace": {
                 "addressPrefixes": [
                   "[variables('vnetAddressPrefix')]"
                 ]
               },
               "subnets":[
                   {
                       "name": "[variables('subnet1Name')]",
                       "properties":{
                           "addressPrefix": "[variables('subnet1Prefix')]"
                       }
                   },
                   {
                     "name": "[variables('subnet2Name')]",
                     "properties":{
                         "addressPrefix": "[variables('subnet2Prefix')]"
                     }
                 }
               ]
             }
         }
     ],
     "outputs": {
        
     }
}

Bon, comme on peut le voir, c'est plutôt verbeux... Mais pour moi là n’est pas le problème, c’est que pour rajouter un subnet à notre VNET, il faut soit passer par un autre template ARM qui ajoute des subnets, ce qui est plutôt compliqué pour les rejouer si on a ajouté 3/4 subnets entre le temps de création du VNET et la nouvelle exécution de ce template sur une autre souscription. Pour parer cela, il est possible d’utiliser des objets complexes, et des fonctions intégrées aux templates ARM, tel que la copy. Cela nous donnerait donc ce script si je l’applique sur le même principe :

{
     "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
     "contentVersion": "1.0.0.0",
     "parameters": {
         "vnetName": {
             "type":"string",
             "defaultValue": "demo-vnet",
             "metadata": {
                 "description" : "Virtual network name"
             }
         },
         "vnetAddressPrefix": {
             "type": "string",
             "defaultValue": "16.0.0.0/16",
             "metadata": {
                 "description": "Address prefix"
             }
         },
         "subnets":{
             "type": "array",
             "defaultValue": [
                 {
                     "Name": "Front",
                     "Prefix": "16.0.1.0/24"
                 },
                 {
                     "Name": "Middle",
                     "Prefix": "16.0.2.0/24"
                 },
                 {
                     "Name": "Back",
                     "Prefix": "16.0.3.0/24"
                 }
             ],
             "metadata": {
                 "description" : "Subnets list to create"
             }
         }
     },
     "variables": {
         "vnetName":"[parameters('vnetName')]",
         "vnetAddressPrefix": "[parameters('vnetAddressPrefix')]",
         "subnets": "[parameters('subnets')]"
     },
     "resources": [
         {
             "apiVersion": "2015-06-15",
             "type": "Microsoft.Network/virtualNetworks",
             "name": "[variables('vnetName')]",
             "location": "[resourceGroup().location]",
             "properties": {
               "addressSpace": {
                 "addressPrefixes": [
                   "[variables('vnetAddressPrefix')]"
                 ]
               },
               "copy": [
                   {
                       "name": "subnets",
                       "count": "[length(variables('subnets'))]",
                       "input": {
                           "name": "[variables('subnets')[copyIndex('subnets')].Name]",
                           "properties": {
                               "addressPrefix": "[variables('subnets')[copyIndex('subnets')].Prefix]"
                           }
                       }
                   }
               ]
             }
         }
     ],
     "outputs": {
        
     }
}

Alors, effectivement en terme de verbosité on ne gagne pas tant de ligne que cela, mais on a l’avantage de garder toujours le même template pour modifier notre VNET et y ajouter différents subnets.

Et sans oublier le lien des templates ARM, si vous le voulez pas copier coller  : https://github.com/wilfriedwoivre/demo-blog/tree/master/ARM/Tips%20VNET%20creation


Remonter

Trucs et astuces avec Windows Azure Table Storage

MAI10

En ce vendredi quasiment férié…. je vous donne une petite astuce pour valider vos connexion avec le Table Storage.

 

Bon je suppose que vous connaissez tous la classe CloudStorageAccount, vu que le Table Storage c’est la vie. En ce moment je travaille beaucoup sur des outils génériques autour du Table Storage pour changer. J’ai donc une problématique, je dois valider que la chaine de connexion saisie par l’utilisateur est bien valide.

 

Alors pour rappel, il est possible de créer une instance de CloudStorageAccount de deux façons :

string accountKey = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
string accountName = "azertyqsdfgh";

var csa = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
var csa2 = CloudStorageAccount.Parse(string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", accountKey, accountName));

 

Le problème, c’est qu’avec cette méthode il est tout à fait possible de créer un CloudStorageAccount, mais cela ne nous dit pas s’il correspond à un vrai storage derrière, ce qui peut être problématique dans de nombreux cas.

Alors tant que Microsoft ne nous fournit pas une méthode simple de validation, il faut tout simplement réaliser une requête vers notre storage afin de savoir qu’il y a bien quelque chose derrière. Je vous conseille de faire un test non intrusif, donc par exemple lister les tables, les blobs ou les queues, mais en aucun cas créer un élément de “test” afin de voir que cela répond bien.

Et vu que je suis un grand seigneur aujourd’hui (comme tous les jours) je vous fournis ma méthode d’extension qui fait cela.

 

public static bool ValidateStorageAccount(this CloudStorageAccount storageAccount)
{
    if (storageAccount == null) throw new  ArgumentNullException("storageAccount");

    var tableClient = storageAccount.CreateCloudTableClient();
    try
    {
        tableClient.ListTablesSegmented(string.Empty, 1, null);
    }
    catch(StorageException ex)
    {
        return false;
    }

    return true;
}

 

A noter, que si c’est la clé du storage qui est mauvaise, j’ai une erreur 403, et si c’est le storage qui n’existe, c’est plus long déjà lors de l’execution, et je récupère une erreur comme quoi l’url est introuvable.

Et pour finir, je vous donne un lien vers un super article qui parle du Table Storage  :  Windows Azure Table Storage 2.0 Qu’est ce qui a changé ? écrit par moi.


Remonter

Windows Azure Global Bootcamp

AVRI24

Comme vous avez pu le remarquer, je ne blog plus trop sur mon blog personnel en ce moment, mais beaucoup plus sur celui de Soat, n’hésitez pas à y faire un tour, ça parle beaucoup de Windows Azure : http://blog.soat.fr

 

De plus je ne reste pas inactif, je suis toujours avec la communauté ZeCloud pour parler d’Azure ! Et d’ailleurs, ce samedi 27 avril, nous organisons la version parisienne du Global Windows Azure Bootcamp.

 

bootcamp

 

Cela se déroulera dans les locaux de Spark de 10h à 18h30, au programme il y aura du fun, de la bonne ambiance, des sessions de qualité, et surtout beaucoup d’Azure! Bref une journée comme je les aime!

Il n’est pas encore trop tard pour vous inscrire, il reste quelques places : http://bit.ly/GWABParis


Remonter

© Wilfried Woivré, tous droits réservés février 2018