{"id":33123,"date":"2019-10-31T21:50:52","date_gmt":"2019-10-31T18:50:52","guid":{"rendered":"https:\/\/prohoster.info\/blog\/terraformer-infrastructure-to-code\/"},"modified":"2019-10-31T21:50:52","modified_gmt":"2019-10-31T18:50:52","slug":"terraformer-infrastructure-to-code","status":"publish","type":"post","link":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/terraformer-infrastructure-to-code","title":{"rendered":"Terraformer \u2014 Infrastructure as Code","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Terraformer \u2014 Infrastructure as Code\" src=\"\/wp-content\/uploads\/2019\/05\/d97414f6b4608dbb4ec7f582b7001773.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nJe voudrais parler d'un nouvel outil CLI que j'ai d\u00e9velopp\u00e9 pour r\u00e9soudre un ancien probl\u00e8me. <\/p>\n<h3>Le probl\u00e8me<\/h3>\n<p>\nTerraform est d\u00e9j\u00e0 devenu une norme dans la communaut\u00e9 DevOps\/Cloud\/IT. C'est un outil tr\u00e8s pratique et utile pour g\u00e9rer l'infrastructure en tant que code. Il y a beaucoup d'avantages \u00e0 utiliser Terraform, mais aussi de nombreux pi\u00e8ges, couteaux aiguis\u00e9s et obstacles. <br \/>\nAvec Terraform, il est tr\u00e8s facile de cr\u00e9er de nouvelles choses, puis de les g\u00e9rer, les modifier ou les supprimer. Mais que faire si l'on dispose d'une grande infrastructure dans le cloud qui n'a pas \u00e9t\u00e9 cr\u00e9\u00e9e avec Terraform ? R\u00e9\u00e9crire et recr\u00e9er tout le cloud peut \u00eatre co\u00fbteux et risqu\u00e9. <br \/>\nJ'ai rencontr\u00e9 ce probl\u00e8me dans deux emplois, le plus simple \u00e9tant de vouloir que tout soit sous git sous forme de fichiers Terraform, alors qu'il y a plus de 250 buckets et qu'\u00e9crire manuellement des fichiers Terraform pour tous cela repr\u00e9sente beaucoup de travail. <br \/>\nOui <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/hashicorp\/terraform\/issues\/581\">issue<\/a><\/noindex> Depuis 2014, avec Terraform qui a \u00e9t\u00e9 ferm\u00e9 en 2016, en esp\u00e9rant qu'il serait possible d'importer.<\/p>\n<p>En gros, tout est comme sur l'image, mais de droite \u00e0 gauche.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Avertissement : L'auteur vit depuis longtemps hors de Russie et \u00e9crit peu en russe. Faites attention aux fautes d'orthographe.<\/p>\n<h3>Solutions<\/h3>\n<p>\n1. Il existe des solutions existantes et anciennes pour AWS. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dtan4\/terraforming\">terraforming<\/a><\/noindex>. Lorsque j'ai essay\u00e9 de r\u00e9cup\u00e9rer mes 250+ buckets avec cela, j'ai compris que c'\u00e9tait en mauvais \u00e9tat. AWS a depuis longtemps ajout\u00e9 de nombreuses nouvelles options dont terraforming n'est pas au courant, et de plus, il utilise Ruby. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dtan4\/terraforming\/blob\/master\/lib\/terraforming\/template\/tf\/s3.erb\">Les templates semblent peu fournis.<\/a><\/noindex>. Apr\u00e8s avoir envoy\u00e9 un email le soir \u00e0 deux heures, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dtan4\/terraforming\/pull\/396\">demande de tirage<\/a><\/noindex> pour ajouter plus de fonctionnalit\u00e9s l\u00e0-dedans, j'ai compris que ce type de solution ne convenait pas du tout. <br \/>\nComment fonctionne terraforming ? Il prend des donn\u00e9es de l'API SDK AWS et g\u00e9n\u00e8re des fichiers tf et tfstate \u00e0 partir de templates. <br \/>\nIl y a trois probl\u00e8mes :<br \/>\n1. Il y aura toujours un retard dans les mises \u00e0 jour.<br \/>\n2. Les fichiers tf sont parfois corrompus. <br \/>\n3. Le tfstate est g\u00e9n\u00e9r\u00e9 s\u00e9par\u00e9ment du tf et ne correspond pas toujours.<br \/>\nEn g\u00e9n\u00e9ral, il est difficile d'obtenir un r\u00e9sultat o\u00f9 `terraform plan` affiche qu'il n'y a pas de changements.<\/p>\n<p>2. `terraform import` est une commande int\u00e9gr\u00e9e \u00e0 Terraform. Comment \u00e7a fonctionne ? <br \/>\nVous \u00e9crivez un fichier TF vide avec le nom et le type de la ressource, puis vous ex\u00e9cutez `terraform import` et transmettez l'ID de la ressource. Terraform interroge le fournisseur, r\u00e9cup\u00e8re les donn\u00e9es et cr\u00e9e un fichier tfstate. <br \/>\nIl y a trois probl\u00e8mes :<br \/>\n1. Vous obtenez seulement le fichier tfstate, le tf est vide et doit \u00eatre \u00e9crit manuellement ou converti depuis le tfstate.<br \/>\n2. Cela ne fonctionne qu'avec une seule ressource \u00e0 la fois et ne prend pas en charge toutes les ressources. Et que dois-je faire de mes 250+ buckets ?<br \/>\n3. Vous devez conna\u00eetre les ID des ressources, c'est-\u00e0-dire que vous devez envelopper cela dans du code qui r\u00e9cup\u00e8re la liste des ressources.<br \/>\nEn g\u00e9n\u00e9ral, le r\u00e9sultat est partiel et n'est pas facilement \u00e9volutif.<\/p>\n<h3>Ma solution<br \/>\n<\/h3>\n<p>Exigences :<br \/>\n1. Possibilit\u00e9 de cr\u00e9er des fichiers tf et tfstate \u00e0 partir des ressources. Par exemple, t\u00e9l\u00e9charger tous les buckets\/groupe de s\u00e9curit\u00e9\/\u00e9quilibreur de charge et ce que `terraform plan` a renvoy\u00e9 qu'il n'y a pas de modifications<br \/>\n2. Deux clouds GCP + AWS<br \/>\n3. Solution globale facile \u00e0 mettre \u00e0 jour \u00e0 chaque fois, sans passer trois jours de travail sur chaque ressource<br \/>\n4. Faire en open source \u2014 c'est un probl\u00e8me que tout le monde rencontre<\/p>\n<p>Langage Go \u2014 c'est pourquoi je l'aime, et il existe une biblioth\u00e8que pour cr\u00e9er des fichiers HCL qui sont utilis\u00e9s dans terraform + beaucoup de code dans terraform qui peut \u00eatre utile<\/p>\n<h3>Chemin<\/h3>\n<p>\nPremi\u00e8re tentative<br \/>\nJ'ai commenc\u00e9 par une version simple. Appels au cloud via SDK pour obtenir la ressource n\u00e9cessaire et la convertir en champs pour terraform. La tentative a \u00e9chou\u00e9 imm\u00e9diatement sur le groupe de s\u00e9curit\u00e9 car je n'ai pas aim\u00e9 convertir seulement le groupe de s\u00e9curit\u00e9 pendant 1,5 jour (et il y a beaucoup de ressources). C'est long et ensuite les champs peuvent changer\/\u00eatre ajout\u00e9s<\/p>\n<p>Deuxi\u00e8me tentative<br \/>\nBas\u00e9e sur l'id\u00e9e d\u00e9crite <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/hashicorp\/terraform\/issues\/15608\">ici<\/a><\/noindex>. Il suffit de prendre et de convertir tfstate en tf. Toutes les donn\u00e9es sont l\u00e0 et les champs sont les m\u00eames. Comment obtenir un tfstate complet pour plusieurs ressources ? Ici, la commande `terraform refresh` est venue \u00e0 mon aide. Terraform prend toutes les ressources dans tfstate et extrait les donn\u00e9es par ID, puis \u00e9crit tout dans tfstate. C'est-\u00e0-dire cr\u00e9er un tfstate vide uniquement avec des noms et IDs, lancer `terraform refresh` et nous obtenons des tfstate complets. Hourra !<br \/>\nNous allons maintenant \u00e9crire un convertisseur pour tfstate vers tf de mani\u00e8re r\u00e9cursive. Pour ceux qui n'ont jamais lu tfstate, c'est JSON, mais particulier. <br \/>\nVoici sa partie importante attributes<\/p>\n<pre><code class=\"javascript\"> \"attributes\": {\n                            \"id\": \"default\/backend-logging-load-deployment\",\n                            \"metadata.#\": \"1\",\n                            \"metadata.0.annotations.%\": \"0\",\n                            \"metadata.0.generate_name\": \"\",\n                            \"metadata.0.generation\": \"24\",\n                            \"metadata.0.labels.%\": \"1\",\n                            \"metadata.0.labels.app\": \"backend-logging\",\n                            \"metadata.0.name\": \"backend-logging-load-deployment\",\n                            \"metadata.0.namespace\": \"default\",\n                            \"metadata.0.resource_version\": \"109317427\",\n                            \"metadata.0.self_link\": \"\\\/apis\\\/apps\\\/v1\\\/namespaces\\\/default\\\/deployments\\\/backend-logging-load-deployment\",\n                            \"metadata.0.uid\": \"300ecda1-4138-11e9-9d5d-42010a8400b5\",\n                            \"spec.#\": \"1\",\n                            \"spec.0.min_ready_seconds\": \"0\",\n                            \"spec.0.paused\": \"false\",\n                            \"spec.0.progress_deadline_seconds\": \"600\",\n                            \"spec.0.replicas\": \"1\",\n                            \"spec.0.revision_history_limit\": \"10\",\n                            \"spec.0.selector.#\": \"1\",\n<\/code><\/pre>\n<p>\nIci, nous avons :<br \/>\n1. id \u2014 cha\u00eene<br \/>\n2. metadata \u2014 tableau de taille 1 contenant un objet avec les champs d\u00e9crits ci-dessous<br \/>\n3. spec \u2014 hachage de taille 1 avec key,value<br \/>\nEn gros, un format amusant, tout peut \u00e9galement \u00eatre imbriqu\u00e9 sur plusieurs niveaux<\/p>\n<pre><code class=\"javascript\">                   \"spec.#\": \"1\",\n                            \"spec.0.min_ready_seconds\": \"0\",\n                            \"spec.0.paused\": \"false\",\n                            \"spec.0.progress_deadline_seconds\": \"600\",\n                            \"spec.0.replicas\": \"1\",\n                            \"spec.0.revision_history_limit\": \"10\",\n                            \"spec.0.selector.#\": \"1\",\n                            \"spec.0.selector.0.match_expressions.#\": \"0\",\n                            \"spec.0.selector.0.match_labels.%\": \"1\",\n                            \"spec.0.selector.0.match_labels.app\": \"backend-logging-load\",\n                            \"spec.0.strategy.#\": \"0\",\n                            \"spec.0.template.#\": \"1\",\n                            \"spec.0.template.0.metadata.#\": \"1\",\n                            \"spec.0.template.0.metadata.0.annotations.%\": \"0\",\n                            \"spec.0.template.0.metadata.0.generate_name\": \"\",\n                            \"spec.0.template.0.metadata.0.generation\": \"0\",\n                            \"spec.0.template.0.metadata.0.labels.%\": \"1\",\n                            \"spec.0.template.0.metadata.0.labels.app\": \"backend-logging-load\",\n                            \"spec.0.template.0.metadata.0.name\": \"\",\n                            \"spec.0.template.0.metadata.0.namespace\": \"\",\n                            \"spec.0.template.0.metadata.0.resource_version\": \"\",\n                            \"spec.0.template.0.metadata.0.self_link\": \"\",\n                            \"spec.0.template.0.metadata.0.uid\": \"\",\n                            \"spec.0.template.0.spec.#\": \"1\",\n                            \"spec.0.template.0.spec.0.active_deadline_seconds\": \"0\",\n                            \"spec.0.template.0.spec.0.container.#\": \"1\",\n                            \"spec.0.template.0.spec.0.container.0.args.#\": \"3\",<\/code><\/pre>\n<p>\nEn gros, si quelqu'un veut un exercice de programmation pour un entretien, il suffit de demander d'\u00e9crire un parseur pour cela \ud83d\ude42<br \/>\nApr\u00e8s de nombreuses tentatives pour \u00e9crire un parseur sans bugs, j'ai trouv\u00e9 une partie de celui-ci dans le code Terraform, d'ailleurs la partie la plus importante. Et tout semblait fonctionner correctement.<\/p>\n<p>Tentative trois<br \/>\nLe fournisseur Terraform est un binaire qui contient le code avec toutes les ressources et la logique pour travailler avec les API des fournisseurs de cloud. Chaque fournisseur de cloud a son propre provider, et Terraform ne les appelle que via son protocole RPC entre deux processus.<br \/>\nMaintenant, j'ai d\u00e9cid\u00e9 de m'adresser directement aux providers Terraform via des appels RPC. \u00c7a s'est tr\u00e8s bien pass\u00e9 et cela a permis de mettre \u00e0 jour les providers Terraform pour en obtenir de nouvelles fonctionnalit\u00e9s sans modifier le code. Il s'est \u00e9galement av\u00e9r\u00e9 que tous les champs du tfstate ne doivent pas n\u00e9cessairement \u00eatre pr\u00e9sents dans le tf, mais comment le savoir ? Il fallait simplement demander au provider. Ensuite, une autre pornographie r\u00e9cursive a commenc\u00e9 avec la compilation de cha\u00eenes de recherche de champs \u00e0 l'int\u00e9rieur du tfstate \u00e0 tous les niveaux.<\/p>\n<p>\u00c0 la fin, j'ai cr\u00e9\u00e9 un outil CLI utile qui a une infrastructure commune pour tous les providers Terraform et il est facile d'ajouter un nouveau. De plus, l'ajout de ressources n\u00e9cessite peu de code. Il y a aussi plein de fonctionnalit\u00e9s comme les connexions entre les ressources. Bien s\u00fbr, il y a eu de nombreux probl\u00e8mes diff\u00e9rents qui ne peuvent pas tous \u00eatre d\u00e9crits.<br \/>\nJ'ai nomm\u00e9 la cr\u00e9ature Terrafomer. <\/p>\n<h3>Final<\/h3>\n<p>\nAvec Terraformer, nous avons g\u00e9n\u00e9r\u00e9 500 \u00e0 700 000 lignes de code tf + tfstate \u00e0 partir de deux clouds. Nous avons pu prendre des choses legacy et commencer \u00e0 les toucher uniquement via Terraform, comme dans les meilleures id\u00e9es d'infrastructure as code. C'est tout simplement magique de prendre un immense cloud et de l'obtenir via une commande sous forme de fichiers Terraform fonctionnels. Ensuite, grep\/replace\/git et ainsi de suite.<\/p>\n<p>J'ai tri\u00e9 et mis en ordre, obtenu les autorisations. J'ai publi\u00e9 sur GitHub pour tout le monde jeudi (02.05.19). <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/GoogleCloudPlatform\/terraformer\">github.com\/GoogleCloudPlatform\/terraformer<\/a><\/noindex><br \/>\nJ'ai d\u00e9j\u00e0 re\u00e7u 600 \u00e9toiles, 2 pull requests ajoutant le support de OpenStack et Kubernetes. De bons retours. C'est vraiment un projet utile pour les gens.<br \/>\nJe le recommande \u00e0 tous ceux qui souhaitent commencer \u00e0 travailler avec Terraform sans tout r\u00e9\u00e9crire pour cela. <br \/>\nJe serais ravi des pull requests, des probl\u00e8mes, des \u00e9toiles.<\/p>\n<p>D\u00e9mo<br \/>\n<noindex><img decoding=\"async\" alt=\"Terraformer \u2014 Infrastructure as Code\" src=\"\/wp-content\/uploads\/2019\/05\/76f10055b9106590f72c4e22e4d4e6d5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/noindex><br \/>\n<br \/>Source : <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/450410\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0425\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e \u043d\u043e\u0432\u044b\u0439 CLI tool \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0440\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 Terraform \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e \u0441\u0442\u0430\u043b \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043e\u043c \u0432 Devops\/Cloud\/IT \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0435. \u0412\u0435\u0449\u044c \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u0447\u0442\u043e\u0431 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u0441\u044f infrastructure as code. \u0415\u0441\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u043b\u0435\u0441\u0442\u0435\u0439 \u0432 Terraform \u0430 \u0442\u0430\u043a \u0436\u0435 \u043c\u043d\u043e\u0433\u043e \u0432\u0438\u043b\u043e\u043a, \u043e\u0441\u0442\u0440\u044b\u0445 \u043d\u043e\u0436\u0435\u0439 \u0438 \u0433\u0440\u0430\u0431\u043b\u0435\u0439. \u0421 Terraform \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0432\u0435\u0449\u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24869,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-33123","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0425\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e \u043d\u043e\u0432\u044b\u0439 CLI tool \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/terraformer-infrastructure-to-code\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47Terraformer \u2014 Infrastructure To Code | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0425\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e \u043d\u043e\u0432\u044b\u0439 CLI tool \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/terraformer-infrastructure-to-code\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:50:52+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:50:52+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Terraformer \u2014 Infrastructure To Code | ProHoster","description":"Je voudrais parler d'un nouvel outil CLI que j'ai \u00e9crit.","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/terraformer-infrastructure-to-code","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47Terraformer \u2014 Infrastructure To Code | ProHoster","og:description":"\u0425\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e \u043d\u043e\u0432\u044b\u0439 CLI tool \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b.","og:url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/terraformer-infrastructure-to-code","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:50:52+00:00","article:modified_time":"2019-10-31T18:50:52+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"33123","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 14:02:48","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:46:23","updated":"2026-01-21 14:02:48","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/33123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=33123"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/33123\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media\/24869"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=33123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=33123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=33123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}