{"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\/sv\/blog\/administrirovanie\/terraformer-infrastructure-to-code","title":{"rendered":"Terraformer \u2014 Infrastruktur till Kod","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Terraformer \u2014 Infrastruktur till Kod\" src=\"\/wp-content\/uploads\/2019\/05\/d97414f6b4608dbb4ec7f582b7001773.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nJag skulle vilja ber\u00e4tta om det nya CLI-verktyget som jag har skrivit f\u00f6r att l\u00f6sa ett gammalt problem. <\/p>\n<h3>Problemet<\/h3>\n<p>\nTerraform har l\u00e4nge blivit standarden inom DevOps\/Cloud\/IT-gemenskapen. Det \u00e4r ett mycket praktiskt och anv\u00e4ndbart verktyg f\u00f6r att arbeta med infrastruktur som kod. Det finns m\u00e5nga f\u00f6rdelar med Terraform, men \u00e4ven m\u00e5nga fallgropar. <br \/>\nMed Terraform \u00e4r det mycket enkelt att skapa nya resurser och sedan hantera, \u00e4ndra eller ta bort dem. Men vad ska man g\u00f6ra om man har en stor infrastruktur i molnet som inte har skapats med Terraform? Att skriva om och \u00e5terskapa hela molnet k\u00e4nns b\u00e5de dyrt och os\u00e4kert. <br \/>\nJag har st\u00f6tt p\u00e5 ett s\u00e5dant problem p\u00e5 tv\u00e5 jobb, det enklaste exemplet \u00e4r n\u00e4r man vill ha allt i git som Terraform-filer, men man har 250+ buckets och det k\u00e4nns som att skriva dem f\u00f6r Terraform f\u00f6r hand \u00e4r alldeles f\u00f6r mycket. <br \/>\nDet finns <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/hashicorp\/terraform\/issues\/581\">problem<\/a><\/noindex> Redan sedan 2014 har det funnits ett Terraform-problem som st\u00e4ngdes 2016 i hopp om att det skulle bli en importfunktion.<\/p>\n<p>Allt \u00e4r i princip som p\u00e5 bilden, men fr\u00e5n h\u00f6ger till v\u00e4nster.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Varningar: F\u00f6rfattaren har bott st\u00f6rre delen av sitt liv utanf\u00f6r Ryssland och skriver s\u00e4llan p\u00e5 ryska. Var f\u00f6rsiktig med stavfel.<\/p>\n<h3>L\u00f6sningar<\/h3>\n<p>\n1. Det finns gamla och f\u00e4rdiga l\u00f6sningar f\u00f6r AWS. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dtan4\/terraforming\">terraforming<\/a><\/noindex>. N\u00e4r jag f\u00f6rs\u00f6kte f\u00e5 mina 250+ buckets genom det ins\u00e5g jag att allt inte fungerade som det skulle. AWS har l\u00e4nge lagt till m\u00e5nga nya alternativ, men terraforming \u00e4r inte medveten om dem och det \u00e4r dessutom skrivet i Ruby. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dtan4\/terraforming\/blob\/master\/lib\/terraforming\/template\/tf\/s3.erb\">mallarna ser skrala ut<\/a><\/noindex>. Efter tv\u00e5 kv\u00e4llar skickade jag <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dtan4\/terraforming\/pull\/396\">Pull request<\/a><\/noindex> f\u00f6r att l\u00e4gga till fler m\u00f6jligheter d\u00e4r och ins\u00e5g att s\u00e5dana l\u00f6sningar inte fungerar \u00f6verhuvudtaget. <br \/>\nHur terraforming fungerar \u00e4r att det h\u00e4mtar data fr\u00e5n AWS SDK och genererar tf och tfstate genom en mall. <br \/>\nDet finns tre problem:<br \/>\n1. Det kommer alltid att finnas en f\u00f6rdr\u00f6jning i uppdateringarna.<br \/>\n2. tf-filerna blir ibland trasiga. <br \/>\n3. tfstate samlas separat fr\u00e5n tf och st\u00e4mmer inte alltid \u00f6verens.<br \/>\nDet \u00e4r generellt sv\u00e5rt att f\u00e5 ett resultat d\u00e4r `terraform plan` s\u00e4ger att det inte finns n\u00e5gra \u00e4ndringar.<\/p>\n<p>2. `terraform import` \u2014 ett inbyggt kommando i Terraform. Hur fungerar det? <br \/>\nDu skriver en tom TF-fil med namnet och typen p\u00e5 resursen, sedan k\u00f6r du `terraform import` och skickar ID:t f\u00f6r resursen. Terraform kontaktar leverant\u00f6ren, f\u00e5r data och skapar en tfstate-fil. <br \/>\nDet finns tre problem:<br \/>\n1. Vi f\u00e5r bara tfstate-filen, medan tf-filen \u00e4r tom och m\u00e5ste skrivas f\u00f6r hand eller konverteras fr\u00e5n tfstate.<br \/>\n2. Kan endast fungera med en resurs i taget och st\u00f6der inte alla resurser. Och vad ska jag g\u00f6ra med 250+ buckets?<br \/>\n3. Man m\u00e5ste veta ID:t f\u00f6r resurserna \u2014 det inneb\u00e4r att man m\u00e5ste sl\u00e5 in det i kod som h\u00e4mtar listan \u00f6ver resurser.<br \/>\nGenerellt \u00e4r resultatet delvis och skalas inte bra.<\/p>\n<h3>Mina l\u00f6sningar<br \/>\n<\/h3>\n<p>Krav:<br \/>\n1. M\u00f6jlighet att skapa tf- och tfstate-filer utifr\u00e5n resurser. Till exempel ladda ner alla buckets\/security groups\/load balancers och vad `terraform plan` returnerade som inga f\u00f6r\u00e4ndringar.<br \/>\n2. Tv\u00e5 moln GCP + AWS<br \/>\n3. En global l\u00f6sning som \u00e4r l\u00e4tt att uppdatera varje g\u00e5ng och som inte kr\u00e4ver tre dagar arbete per resurs.<br \/>\n4. G\u00f6ra det open source \u2014 detta \u00e4r ett problem som alla har.<\/p>\n<p>Spr\u00e5k Go \u2014 d\u00e4rf\u00f6r \u00e4lskar jag det, och det finns ett bibliotek f\u00f6r att skapa HCL-filer som anv\u00e4nds i terraform + mycket kod i terraform som kan vara anv\u00e4ndbar.<\/p>\n<h3>V\u00e4g<\/h3>\n<p>\nF\u00f6rsta f\u00f6rs\u00f6ket<br \/>\nJag b\u00f6rjade med en enkel variant. Anrop till molnet via SDK f\u00f6r att h\u00e4mta den resurs som beh\u00f6vs och konvertera den till f\u00e4lt f\u00f6r terraform. F\u00f6rs\u00f6ket dog direkt p\u00e5 security group eftersom jag inte gillade att det tog 1,5 dagar att konvertera bara security group (det finns m\u00e5nga resurser). L\u00e5ngsamt och sedan kan f\u00e4lten \u00e4ndras\/l\u00e4ggas till.<\/p>\n<p>Andra f\u00f6rs\u00f6ket<br \/>\nBaserat p\u00e5 id\u00e9n som beskrivs <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/hashicorp\/terraform\/issues\/15608\">). Ett typiskt exempel p\u00e5 anv\u00e4ndning:<\/a><\/noindex>. Att helt enkelt ta och konvertera tfstate till tf. Alla data finns d\u00e4r och f\u00e4lten \u00e4r desamma. Hur f\u00e5r man en fullst\u00e4ndig tfstate f\u00f6r m\u00e5nga resurser?? H\u00e4r kom kommandot `terraform refresh` till hj\u00e4lp. Terraform h\u00e4mtar alla resurser i tfstate och drar ut data f\u00f6r dem baserat p\u00e5 ID och skriver allt till tfstate. S\u00e5 skapa en tom tfstate bara med namn och ID, k\u00f6ra `terraform refresh`, och d\u00e5 f\u00e5r vi fullst\u00e4ndiga tfstate. Hurra!<br \/>\nNu ska vi syssla med den rekursiva pornografin att skriva en konverterare f\u00f6r tfstate till tf. F\u00f6r dem som aldrig har l\u00e4st tfstate, s\u00e5 \u00e4r det JSON, men speciellt. <br \/>\nH\u00e4r \u00e4r dess viktiga del egenskaper<\/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>\nH\u00e4r finns:<br \/>\n1. id \u2014 string<br \/>\n2. metadata \u2014 array av storlek 1 och den inneh\u00e5ller ett objekt med f\u00e4lten som beskrivs nedan<br \/>\n3. spec \u2014 hash av storlek 1 och den inneh\u00e5ller key,value<br \/>\nEn kort, underh\u00e5llande format d\u00e4r allt kan g\u00e5 djupare, \u00e4ven p\u00e5 flera niv\u00e5er.<\/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>\nI allm\u00e4nhet, den som vill ha en programmeringsuppgift f\u00f6r en intervju kan helt enkelt be om att f\u00e5 skriva en parser f\u00f6r detta \ud83d\ude42<br \/>\nEfter m\u00e5nga f\u00f6rs\u00f6k att skriva en parser utan buggar, hittade jag en del av den i terraform-koden, n\u00e4mligen den mest kritiska delen. Och allt verkade fungera bra.<\/p>\n<p>F\u00f6rs\u00f6k tre.<br \/>\nTerraform provider \u00e4r bin\u00e4rer som inneh\u00e5ller kod med alla resurser och logik f\u00f6r att arbeta med moln-API:er. Varje moln har sin egen provider och terraform anropar dem enbart genom sitt RPC-protokoll mellan tv\u00e5 processer.<br \/>\nNu har jag beslutat att kontakta terraform-providers direkt via RPC-anrop. Det blev vackert och gav m\u00f6jlighet att byta terraform-providers mot nyare versioner och f\u00e5 nya funktioner utan att \u00e4ndra koden. Det visade sig ocks\u00e5 att inte alla f\u00e4lt i tfstate m\u00e5ste vara i tf, men hur vet man detta? Man m\u00e5ste bara fr\u00e5ga provider om det. Sedan b\u00f6rjade en annan rekursiv process med att bygga regelbundna uttryck och s\u00f6ka efter f\u00e4lt inom tfstate p\u00e5 alla niv\u00e5er.<\/p>\n<p>I slut\u00e4ndan blev det ett anv\u00e4ndbart CLI-verktyg med en gemensam infrastruktur f\u00f6r alla terraform-leverant\u00f6rer, och det \u00e4r enkelt att l\u00e4gga till nya. Dessutom tar till\u00e4gg av resurser lite kod. Plus olika finesser som kopplingar mellan resurser. Det fanns f\u00f6rst\u00e5s m\u00e5nga olika problem som inte g\u00e5r att beskriva alla.<br \/>\nJag d\u00f6pte lilla djuret till Terrafomer. <\/p>\n<h3>Finalen<\/h3>\n<p>\nMed hj\u00e4lp av Terrafomer genererade vi 500-700 tusen rader tf + tfstate-kod fr\u00e5n tv\u00e5 moln. Vi kunde ta tag i legacy-grejer och b\u00f6rja arbeta med dem genom terraform som i de b\u00e4sta id\u00e9erna f\u00f6r infrastruktur som kod. Ren magi n\u00e4r man tar ett stort moln och f\u00e5r det som terraform-filer med ett kommando. Och sedan grep\/replace\/git och s\u00e5 vidare.<\/p>\n<p>Jag r\u00e4knade ut och organiserade, fick tillst\u00e5nd. Sl\u00e4ppte det p\u00e5 GitHub f\u00f6r alla p\u00e5 torsdag (02.05.19). <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/GoogleCloudPlatform\/terraformer\">github.com\/GoogleCloudPlatform\/terraformer<\/a><\/noindex><br \/>\nHar redan f\u00e5tt 600 stj\u00e4rnor, 2 pull requests f\u00f6r att l\u00e4gga till st\u00f6d f\u00f6r openstack och kubernetes. Bra recensioner. Generellt sett \u00e4r projektet anv\u00e4ndbart f\u00f6r m\u00e4nniskor.<br \/>\nJag rekommenderar det till alla som vill b\u00f6rja arbeta med Terraform och inte skriva om allt f\u00f6r detta. <br \/>\nJag ser fram emot pull requests, problem, stj\u00e4rnor.<\/p>\n<p>Demo<br \/>\n<noindex><img decoding=\"async\" alt=\"Terraformer \u2014 Infrastruktur till Kod\" src=\"\/wp-content\/uploads\/2019\/05\/76f10055b9106590f72c4e22e4d4e6d5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/noindex><br \/>\n<br \/>K\u00e4lla: <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.4 - 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\/sv\/blog\/administrirovanie\/terraformer-infrastructure-to-code\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sv_SE\" \/>\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\/sv\/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":"Jag skulle vilja ber\u00e4tta om det nya CLI-verktyget som jag har skrivit.","canonical_url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/terraformer-infrastructure-to-code","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sv_SE","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\/sv\/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\/sv\/wp-json\/wp\/v2\/posts\/33123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/comments?post=33123"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/33123\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media\/24869"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=33123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=33123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=33123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}