{"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\/nl\/blog\/administrirovanie\/terraformer-infrastructure-to-code","title":{"rendered":"Terraformer \u2014 Infrastructuur als Code","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Terraformer \u2014 Infrastructuur als Code\" src=\"\/wp-content\/uploads\/2019\/05\/d97414f6b4608dbb4ec7f582b7001773.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nIk wil een nieuw CLI-hulpmiddel presenteren dat ik heb geschreven om een oud probleem op te lossen. <\/p>\n<h3>Probleem<\/h3>\n<p>\nTerraform is al een tijdje de standaard in de Devops\/Cloud\/IT-gemeenschap. Het is een zeer handige en nuttige tool voor infrastructuur als code. Er zijn veel voordelen aan Terraform, maar ook veel valkuilen en moeilijkheden. <br \/>\nMet Terraform is het heel gemakkelijk om nieuwe dingen te maken en deze vervolgens te beheren, te wijzigen of te verwijderen. Maar wat moeten degenen doen die een enorme infrastructuur in de cloud hebben die niet met Terraform is gemaakt? Alles herschrijven en opnieuw opzetten is kostbaar en onveilig. <br \/>\nIk ben dit probleem tegengekomen op twee banen, het meest eenvoudige voorbeeld is wanneer je alles in git wilt hebben in de vorm van Terraform-bestanden, maar je hebt 250+ buckets en het handmatig schrijven van hun configuraties voor Terraform is wel een hele klus. <br \/>\nEr is <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/hashicorp\/terraform\/issues\/581\">probleem<\/a><\/noindex> sinds 2014 in Terraform dat in 2016 is gesloten in de hoop dat er import zou komen.<\/p>\n<p>In wezen is het allemaal zoals op de afbeelding, maar van rechts naar links<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Waarschuwingen: De auteur leeft al een half leven niet in Rusland en schrijft zelden in het Russisch. Wees voorzichtig met spelfouten.<\/p>\n<h3>Oplossingen<\/h3>\n<p>\n1. Er zijn bestaande en oude oplossingen voor AWS <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dtan4\/terraforming\">terraforming<\/a><\/noindex>. Toen ik probeerde mijn 250+ buckets te verkrijgen via dit hulpmiddel, realiseerde ik me dat het niet goed werkte. AWS heeft al veel nieuwe opties toegevoegd, maar terraforming is daar niet van op de hoogte en het gebruikt bovendien Ruby. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dtan4\/terraforming\/blob\/master\/lib\/terraforming\/template\/tf\/s3.erb\">De sjablonen zien er beperkt uit<\/a><\/noindex>. Na twee avonden heb ik een <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dtan4\/terraforming\/pull\/396\">Pull request<\/a><\/noindex> gestuurd om meer mogelijkheden toe te voegen en ik begreep dat zulke oplossingen helemaal niet geschikt zijn. <br \/>\nHoe werkt terraforming? Het haalt gegevens van de AWS SDK en genereert tf- en tfstate-bestanden via sjablonen. <br \/>\nHier zijn drie problemen:<br \/>\n1. Er zal altijd vertraging zijn in updates<br \/>\n2. tf-bestanden zijn soms beschadigd <br \/>\n3. tfstate wordt apart van tf verzameld en komt niet altijd overeen<br \/>\nOver het algemeen is het moeilijk om een resultaat te krijgen waarbij `terraform plan` aangeeft dat er geen wijzigingen zijn<\/p>\n<p>2. `terraform import` \u2014 een ingebouwd commando in Terraform. Hoe werkt dat? <br \/>\nJe schrijft een leeg TF-bestand met de naam en het type resource, daarna voer je `terraform import` uit en geeft het ID van de resource door. Terraform vraagt de provider om gegevens en maakt het tfstate-bestand aan. <br \/>\nHier zijn drie problemen:<br \/>\n1. We krijgen alleen het tfstate-bestand en het tf-bestand is leeg; dat moet handmatig worden geschreven of geconverteerd vanuit tfstate.<br \/>\n2. Het kan slechts met \u00e9\u00e9n resource per keer werken en ondersteunt niet alle resources. En wat moet ik weer doen met die 250+ buckets?<br \/>\n3. Je moet het ID van de resources kennen; je moet dit dus in code wikkelen die de lijst van resources ophaalt.<br \/>\nHet resultaat is in feite gedeeltelijk en schaalt niet goed.<\/p>\n<h3>Mijn oplossing<br \/>\n<\/h3>\n<p>Vereisten:<br \/>\n1. Mogelijkheid om tf- en tfstate-bestanden te maken op basis van bronnen. Bijvoorbeeld alle buckets\/security groups\/load balancers downloaden en ervoor zorgen dat `terraform plan` aangeeft dat er geen wijzigingen zijn.<br \/>\n2. Twee clouds GCP + AWS<br \/>\n3. Een globale oplossing die gemakkelijk is bij te werken en waarbij niet elke keer drie dagen werk voor elke bron nodig is.<br \/>\n4. Maak het open source \u2014 dit is een probleem dat iedereen heeft.<\/p>\n<p>De taal Go \u2014 daarom hou ik ervan, en er is een bibliotheek voor het cre\u00ebren van HCL-bestanden die wordt gebruikt in terraform + veel code in terraform die nuttig kan zijn.<\/p>\n<h3>Pad<\/h3>\n<p>\nEerste poging<br \/>\nIk begon met een eenvoudige versie. Het maken van verbinding met de cloud via de SDK voor de benodigde bron en deze converteren naar velden voor terraform. De poging stierf onmiddellijk bij de security group omdat ik het niet leuk vond om 1,5 dag alleen de security group te converteren (er zijn veel bronnen). Het duurt lang en vervolgens kunnen de velden veranderen\/toegevoegd worden.<\/p>\n<p>Tweede poging<br \/>\nGebaseerd op het beschreven idee <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/hashicorp\/terraform\/issues\/15608\">here<\/a><\/noindex>. Gewoon het tfstate in tf converteren. Alle gegevens zijn daar en de velden zijn hetzelfde. Hoe krijg je een compleet tfstate voor meerdere bronnen?? Hier kwam het commando `terraform refresh` van pas. Terraform haalt alle bronnen in tfstate op en haalt op basis van ID gegevens op en schrijft alles in tfstate. Dat wil zeggen, maak een leeg tfstate alleen met namen en ID\u2019s, start `terraform refresh` en we ontvangen volledige tfstate. Hoera!<br \/>\nLaten we nu bezig gaan met het recursieve schrijven van een converter van tfstate naar tf. Voor degenen die nog nooit tfstate hebben gelezen, dit is JSON, maar dan speciaal. <br \/>\nHier is het belangrijke deel 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>\nHier zijn:<br \/>\n1. id \u2014 string<br \/>\n2. metadata \u2014 array van grootte 1 en daarin een object met de velden die hieronder worden beschreven<br \/>\n3. spec \u2014 hash van grootte 1 en daarin key,value<br \/>\nEen kort en leuk formaat, alles kan ook diepgaand zijn tot verschillende niveaus.<\/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>\nIn het algemeen, wie een programmeeropdracht voor een sollicitatie wil, vraag gewoon om een parser hiervoor te schrijven \ud83d\ude42.<br \/>\nNa lange pogingen om een parser zonder bugs te schrijven, vond ik een deel ervan in de Terraform-code, en dat was het belangrijkste deel. En alles leek normaal te werken.<\/p>\n<p>Poging drie.<br \/>\nEen Terraform-provider is een binaire versie met code voor alle middelen en logica om met de API's van cloudproviders te werken. Elke cloud heeft zijn eigen provider, en Terraform roept ze aan via zijn RPC-protocol tussen twee processen.<br \/>\nNu besloot ik rechtstreeks contact op te nemen met Terraform-providers via RPC-aanroepen. Het kwam mooi uit en maakte het mogelijk om Terraform-providers te vervangen door nieuwere versies en nieuwe mogelijkheden te krijgen zonder de code te veranderen. Het bleek ook dat niet alle velden in tfstate in tf moeten zitten, maar hoe kom je daarachter? Alleen door de provider ernaar te vragen. Toen begon er nog een recursieve verwarring bij het samenstellen van reguliere expressies met het zoeken naar velden binnen tfstate op alle niveaus.<\/p>\n<p>Uiteindelijk is er een nuttige CLI-tool ontstaan met een gemeenschappelijke infrastructuur voor alle terraform providers, en het is eenvoudig om een nieuwe toe te voegen. Ook duurt het toevoegen van bronnen weinig code. Plus allerlei extra's zoals verbindingen tussen middelen. Natuurlijk waren er veel verschillende problemen die niet allemaal te beschrijven zijn.<br \/>\nIk heb het beestje Terrafomer genoemd. <\/p>\n<h3>Eind<\/h3>\n<p>\nMet Terrafomer hebben we 500-700 duizend regels tf + tfstate-code gegenereerd in twee cloudomgevingen. We konden legacy elementen oppakken en ze alleen via terraform aanpakken, zoals het beste idee van infrastructure as code. Het is gewoon magie als je een enorme cloud pakt en deze met een commando in de vorm van werkende terraform-bestanden krijgt. En dan grep\/replace\/git en zo verder.<\/p>\n<p>Ik heb alles berekend en op orde gebracht, kreeg de juiste machtigingen. Heb het op GitHub uitgegeven voor iedereen op donderdag (02.05.19). <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/GoogleCloudPlatform\/terraformer\">github.com\/GoogleCloudPlatform\/terraformer<\/a><\/noindex><br \/>\nIk heb inmiddels 600 sterren gekregen, 2 pull requests voor de ondersteuning van openstack en kubernetes toegevoegd. Goede feedback. Het project is over het algemeen nuttig voor mensen.<br \/>\nIk raad het iedereen aan die met Terraform wil beginnen en niet alles opnieuw wil schrijven. <br \/>\nIk ben blij met pull requests, issues, sterren.<\/p>\n<p>Demo<br \/>\n<noindex><img decoding=\"async\" alt=\"Terraformer \u2014 Infrastructuur als Code\" src=\"\/wp-content\/uploads\/2019\/05\/76f10055b9106590f72c4e22e4d4e6d5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/noindex><br \/>\n<br \/>Bron: <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.3 - 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\/nl\/blog\/administrirovanie\/terraformer-infrastructure-to-code\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"nl_NL\" \/>\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\/nl\/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":"Ik wil het graag hebben over de nieuwe CLI-tool die ik heb geschreven.","canonical_url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/terraformer-infrastructure-to-code","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nl_NL","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\/nl\/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\/nl\/wp-json\/wp\/v2\/posts\/33123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/comments?post=33123"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/33123\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media\/24869"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media?parent=33123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/categories?post=33123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/tags?post=33123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}