<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Gwendal Leclerc, Author at OVHcloud Blog</title>
	<atom:link href="https://blog.ovhcloud.com/author/gwendal-leclerc/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.ovhcloud.com</link>
	<description>Innovation for Freedom</description>
	<lastBuildDate>Mon, 03 Jul 2023 08:15:36 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://blog.ovhcloud.com/wp-content/uploads/2019/07/cropped-cropped-nouveau-logo-ovh-rebranding-32x32.gif</url>
	<title>Gwendal Leclerc, Author at OVHcloud Blog</title>
	<link>https://blog.ovhcloud.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Domain name registration gone wrong</title>
		<link>https://blog.ovhcloud.com/domain-name-registration-gone-wrong/</link>
		
		<dc:creator><![CDATA[Mathieu Cornic,&#160;Gwendal Leclerc&#160;and&#160;Johan Hennache]]></dc:creator>
		<pubDate>Tue, 08 Feb 2022 13:45:09 +0000</pubDate>
				<category><![CDATA[OVHcloud Engineering]]></category>
		<category><![CDATA[Domain names]]></category>
		<guid isPermaLink="false">https://blog.ovhcloud.com/?p=21202</guid>

					<description><![CDATA[In the last article, we introduced you about what a domain name is, what entities are involved and what the purpose of the Whois is. As seen previously, OVHcloud is a registrar. As a registrar, our work is very similar to that of a real estate agency. We connect tenants (registrants) with landlords (registries) and [&#8230;]<img src="//blog.ovhcloud.com/wp-content/plugins/matomo/app/matomo.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fblog.ovhcloud.com%2Fdomain-name-registration-gone-wrong%2F&amp;action_name=Domain%20name%20registration%20gone%20wrong&amp;urlref=https%3A%2F%2Fblog.ovhcloud.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[
<p>In the last article, we introduced you about what a domain name is, what entities are involved and what the purpose of the Whois is.</p>



<p>As seen previously, <strong>OVHcloud is a registrar</strong>. As a registrar, our work is very similar to that of a real estate agency. We connect tenants (registrants) with landlords (registries) and get a margin for each transaction. As a registrant, when you order a new domain name, you rent it for a given period (often 1 year), which can be extended until you don&#8217;t want it anymore.</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img fetchpriority="high" decoding="async" src="https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0795-1024x537.jpeg" alt="Domain name registration gone wrong" class="wp-image-22268" width="768" height="403" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0795-1024x537.jpeg 1024w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0795-300x157.jpeg 300w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0795-768x403.jpeg 768w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0795.jpeg 1200w" sizes="(max-width: 768px) 100vw, 768px" /></figure></div>



<p>In this article, we will show you what happens behind the scenes&nbsp;when you order and manage a domain name. <strong>Through a story, we will explain what the domain lifecycle&nbsp;is and how we interact with registries.</strong></p>



<h2 class="wp-block-heading" id="Article2-Lifecycle">Lifecycle</h2>



<p>Let&#8217;s say you read our <a href="https://www.ovh.com/blog/understanding-the-anatomy-of-gpus-using-pokemon/" data-wpel-link="exclude">blog article about the anatomy of GPUs using Pokémon</a>, and want to start a business selling GPU Pokémon cards. You spent a lot a time thinking about the best domain name to register, and came up with <strong>pokegpu.com</strong>&nbsp;</p>



<p>Our story starts on the 12th July 2021, you are ready to start your business. You go to the OVHcloud website and <a href="https://www.ovh.ie/order/webcloud/?form_id=domain_search_form#/webCloud/domain/select?selection=~(domains~(list~(~(name~%27pokegpu.com))~options~(~%27dnssec)))" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">search this&nbsp;domain name</a>.</p>



<p><em>In the following sections, for readability, periods of 30 and 60 days will be simplified respectively as 1 month and 2 months. It means that when 1st August is increased by 30 days, it will appear as 1st September and not 31th August.&nbsp;</em></p>



<h3 class="wp-block-heading" id="Article2-2021-DomainNameRegistration">2021 &#8211; Domain Name Registration</h3>



<p>First of all, when you search for&nbsp;<strong>pokegpu.com</strong>, OVHcloud information system will make a check to ensure that:</p>



<ol class="wp-block-list"><li>We sell the<em> .com</em> extension</li><li>There is no ongoing maintenance on the registry backend, Verisign in the case of <em>.com</em>.</li><li>The domain is available on the registry backend (also known as &#8220;Domain Check&#8221;)</li></ol>



<p>Luckily, no one seems to want to sell GPU Pokémon cards, so you are free to order the domain name. Once the order is paid, we are able to start the creation of your domain name.</p>



<p>Depending on the extension, you may have to fulfill some requirements, like being a European Union citizen or resident for .eu extension (more on this in the next article). For the <em>.com</em> extension, no need to worry, the extension is available for everyone and there are no specific requirements.</p>



<p>On OVHcloud side, we will create the reference of your domain internally, and communicate with the registry backend by sharing some elements:</p>



<ul class="wp-block-list"><li>Contacts data: owner, administrator, technical (more details about this in our next article)</li><li>Dates of creation and expiration</li><li>DNS servers (set by default or personalized in the order funnel)</li></ul>



<p>In this creation phase, an anonymized working version of your email is sent to the registry backend, so you can avoid spam by regenerating another&nbsp;if needed.&nbsp;</p>



<p>If transmitted information is correct, the creation of your domain is finalized in a short time.</p>



<p>Finally, by default, we transparently protect the domain name from unwanted transfers, by sending a command to the registry backend. So you will need to deliberately disable the protection if you want to transfer your domain name to another registrar.</p>



<p>As this is a new business and you are not sure that the company is viable, you decide&nbsp;to disable the OVHcloud auto-renew. It means the domain will have&nbsp;to be manually renewed before expiration, otherwise it will be deleted. Don&#8217;t worry, you will be notified before it happens.</p>



<p>It will require a manual renewal before&nbsp;12th July 2022.</p>



<h3 class="wp-block-heading" id="Article2-2022-FirstDomainRenew">2022 &#8211; First Domain Renew</h3>



<p>We are now 10 months later (60 days before expiration), the 12th May 2022. Nice, your business works well and you sell your PokeGPU cards all around the world&nbsp;<img decoding="async" src="https://docs.dsi.ovh/s/k1pe7c/8401/704793d6038510d343805f57baea5ca16b469eae/_/images/icons/emoticons/smile.svg" alt="(smile)">.</p>



<p>But <strong>pokegpu.com</strong> is almost expired, so you receive a first notification. As you want to keep selling cards, you <a href="https://www.ovh.ie/domains/domain_renewal.xml" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">renew&nbsp;the domain name</a> the 13th May 2022 for 2 years.</p>



<p>A renewal command is sent&nbsp;by our system to Verisign which adds two years to the expiration date.</p>



<p>It will now expire the 12th July 2024.</p>



<h3 class="wp-block-heading" id="Article2-2024-ForgottenRenewal">2024 &#8211; Forgotten Renewal</h3>



<p>Two years have passed, you now&nbsp;have refocused on another business leaving the sale of&nbsp;GPU Pokémon cards aside for now. And in doing so, even after all the notifications (60 days, 30 days, 15 days, 7 days and 3 days prior to the expiration), you forgot to manually renew your domain name. The domain name expires the 12th July 2024.</p>



<p>This domain name, as well as the other gTLDs, are by default automatically renewed by the registry using the &#8220;registry auto-renew&#8221; feature. When the domain name expires, it&#8217;s renewed on the registry side, and an auto-renew grace period starts for up to 45 days, during which registrars can request the deletion of the domain name so that they are not charged for the renew.</p>



<p>It has to be differentiated from the OVHcloud auto-renew feature. OVHcloud auto-renew is possible on gTLDs extensions but also on the ones which do not support registry auto-renew. Here is a matrix to summarize which cases are possible and how the workflow changes.</p>



<figure class="wp-block-table"><table><thead><tr><th></th><th><strong>Registry auto-renew enabled (gTLDs)</strong></th><th><strong>Registry auto-renew disabled or absent (ccTLDs)</strong></th></tr></thead><tbody><tr><td>OVHcloud auto-renew enabled</td><td>We synchronize our system on registry expiration date, but don&#8217;t interact with the registry backend. It&#8217;s transparent on your end.</td><td>We send an explicit renewal request automatically for you before expiration. It&#8217;s transparent on your end.</td></tr><tr><td>OVHcloud auto-renew disabled</td><td>If you do not renew within 30 days after expiration, we send an explicit deletion request to the registry. This will make the domain name fall in redemption grace period for 30 days. In this period, the domain name can still be restored from the registry with additional fees.</td><td>We let the domain name fall in redemption grace period if you do not renew it. From ccTLDs registry to another, periods may differ and restore may be possible or not.</td></tr></tbody></table></figure>



<p>Let&#8217;s come back to what happened for the expiration of your domain&nbsp;<strong>pokegpu.com:</strong></p>



<ol class="wp-block-list"><li>As a registrar, when the expiration date was reached, we sent a command to suspend the domain name to the registry.&nbsp;This made the domain name unavailable, as well as the services hosted behind it (email, website&#8230;)</li><li>As it&#8217;s a gTLD, we waited for 30 days to let you renew the domain, in order to give you a the opportunity&nbsp;to renew during the auto-renew grace period</li><li>As it was not renewed during this period, we sent an explicit command to request deletion of the domain name to the registry.&nbsp;The domain name then&nbsp;fell in redemption grace period for 30 days. During this period, the domain name can still be restored from the registry</li></ol>



<p>Now you have two choices:</p>



<ol class="wp-block-list"><li>You let it expire&nbsp;and&nbsp;5 days after the end of redemption, it will be available again for registration by anyone (even by a malicious person)</li><li>You absolutely do not want to take the risk of losing the domain name and ask for a restore</li></ol>



<h3 class="wp-block-heading" id="2024-restoration">2024 &#8211; Restoration</h3>



<p>The domain is suspended and almost lost, it will return to the public domain in a couple of days. Grace period of 30 days expired, but the domain name can be restored. You don&#8217;t want to take the risk of having it taken over by someone else, so after some days of thought, you decide to keep your domain name for a little longer and explicitly restore the domain&nbsp;on&nbsp;the&nbsp;20th August 2024.</p>



<p>This action is very similar to the renewal, but registries often ask for a much more expensive price (about 400% increase for .com).&nbsp;</p>



<p>A restore command is sent to Verisign, which adds one year to the expiration date and reactivates&nbsp;the domain name. After the operation, the domain name is fully working and related hosted services become available again.</p>



<h3 class="wp-block-heading" id="2024-secure-renew-with-ovhcloud-auto-renew">2024 &#8211; Secure renew with OVHcloud auto-renew</h3>



<p>To avoid such trouble, at OVHcloud&nbsp;we decided to enable&nbsp;the OVHcloud auto-renew feature by default for new domain name registrations.</p>



<p>On the 21st&nbsp;August 2024, you decide to re-enable it. As long as a valid payment method is configured on your account, the domain name will be automatically renewed every year without any action on your end.</p>



<p>You can now focus on your new business with peace of mind&nbsp;<img decoding="async" src="https://docs.dsi.ovh/s/k1pe7c/8401/704793d6038510d343805f57baea5ca16b469eae/_/images/icons/emoticons/smile.svg" alt="(smile)">&nbsp;. The domain will be renewed on&nbsp;the&nbsp;12th July 2025, the anniversary of the creation date, and in the following years until you decide not to.&nbsp;</p>



<h2 class="wp-block-heading" id="summary">Summary</h2>



<p>Here is a timeline summarizing what happened:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" width="672" height="1024" src="https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0797-672x1024.jpeg" alt="a timeline summarizing what happened:" class="wp-image-22272" title="PU Domain &gt; Article 2 &gt; BlogArticle2_Timeline.png" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0797-672x1024.jpeg 672w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0797-197x300.jpeg 197w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0797-768x1170.jpeg 768w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0797-1009x1536.jpeg 1009w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0797-1345x2048.jpeg 1345w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0797.jpeg 1488w" sizes="(max-width: 672px) 100vw, 672px" /></figure></div>



<p>This timeline happened because a gTLD domain name lifecycle corresponds to the following simplified graph.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" width="1024" height="384" src="https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0796-1024x384.jpeg" alt="This timeline happened because a gTLD domain name lifecycle corresponds to the following simplified graph." class="wp-image-22270" title="PU Domain &gt; Article 2 &gt; BlogArticle2_Lifecycle.png" srcset="https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0796-1024x384.jpeg 1024w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0796-300x113.jpeg 300w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0796-768x288.jpeg 768w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0796-1536x576.jpeg 1536w, https://blog.ovhcloud.com/wp-content/uploads/2022/02/IMG_0796-2048x768.jpeg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>



<ol class="wp-block-list"><li>Domain name is available for registration to everyone</li><li>Domain name is registered for 1 to 10 years. The domain can be renewed by the customer in this period. If the expiration date is reached without renew, the domain name expires</li><li>Domain name is expired. It&#8217;s suspended and services hosted behind&nbsp;it are not available anymore. When the registry auto-renew feature is activated (to not mix up with OVHcloud auto-renew), registrars have up to 45 days to cancel the automatic renewal. At OVHcloud, we give customers 30 days to renew</li><li>Domain name is restorable. It&#8217;s still suspended and can be restored, which is similar to a renew but with redemption fees</li><li>Domain name is blocked in deletion for 5 days. It&#8217;s still suspended, and domain name will be available again for registration at the end of the period</li></ol>



<h2 class="wp-block-heading" id="conclusion">Conclusion</h2>



<p>In this post, we talked about the lifecycle of&nbsp;<em>a</em>&nbsp;<em>single</em>&nbsp;domain name. But the truth is that this story only relates to the lifecycle of a gTLD. ccTLDs belong to a whole new world, often with eligibility rules and a custom lifecycle.&nbsp;</p>



<p>For instance, .es domain names don&#8217;t support automated restore, .it domain names have a renew grace period of 13 days, .pl domain names are not renewed on transfer&#8230; All these are special cases we need to integrate in our information system. As as registrar, our role is to lessen these differences by giving a standardized user experience to our customers.</p>



<p>In the next article, we will talk about eligibility rules and how some extensions cannot be owned by anyone.</p>
<img loading="lazy" decoding="async" src="//blog.ovhcloud.com/wp-content/plugins/matomo/app/matomo.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fblog.ovhcloud.com%2Fdomain-name-registration-gone-wrong%2F&amp;action_name=Domain%20name%20registration%20gone%20wrong&amp;urlref=https%3A%2F%2Fblog.ovhcloud.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Declarative integration tests in a microservice environment</title>
		<link>https://blog.ovhcloud.com/declarative-integration-tests-in-a-microservice-environment/</link>
		
		<dc:creator><![CDATA[Thibaut Rousseau&#160;and&#160;Gwendal Leclerc]]></dc:creator>
		<pubDate>Thu, 27 Aug 2020 15:20:01 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Microservices]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://www.ovh.com/blog/?p=19110</guid>

					<description><![CDATA[At OVHcloud, the Domain Names team currently manages a total of 5 millions domain names. To handle this volume, and anticipate future growth, we have been migrating our information system from a monolith to a microservice-inspired architecture. Although this ongoing migration presents lots of advantages over the monolithic approach (scalability being the most obvious), a [&#8230;]<img src="//blog.ovhcloud.com/wp-content/plugins/matomo/app/matomo.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fblog.ovhcloud.com%2Fdeclarative-integration-tests-in-a-microservice-environment%2F&amp;action_name=Declarative%20integration%20tests%20in%20a%20microservice%20environment&amp;urlref=https%3A%2F%2Fblog.ovhcloud.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" src="https://www.ovh.com/blog/wp-content/uploads/2020/08/4EEE15D2-607A-4101-860C-24F9AD7A75F8-1024x537.png" alt="Declarative integration tests in a microservice environment" class="wp-image-19159" width="512" height="269" srcset="https://blog.ovhcloud.com/wp-content/uploads/2020/08/4EEE15D2-607A-4101-860C-24F9AD7A75F8-1024x537.png 1024w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/4EEE15D2-607A-4101-860C-24F9AD7A75F8-300x157.png 300w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/4EEE15D2-607A-4101-860C-24F9AD7A75F8-768x403.png 768w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/4EEE15D2-607A-4101-860C-24F9AD7A75F8.png 1200w" sizes="auto, (max-width: 512px) 100vw, 512px" /></figure></div>



<p>At <strong>OVHcloud</strong>, the Domain Names team currently manages a total of 5 millions domain names. To handle this volume, and anticipate future growth, we have been migrating our information system from a monolith to a microservice-inspired architecture. </p>



<p>Although this ongoing migration presents lots of advantages over the monolithic approach (scalability being the most obvious), a few challenges arise as we progress towards our goal. By their nature, microservices imply a lot more network messages (HTTP in our case) and have a lot more dependencies on external services; such as databases, caches, queues, etc. In this context, unit testing each service individually is not enough. Testing the integration between all the services becomes critical.</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" src="https://www.ovh.com/blog/wp-content/uploads/2020/08/88F1A300-DEB2-4708-8019-67FBC90E098F.png" alt="Unit tests vs Integration tests" class="wp-image-19161" width="326" height="180" srcset="https://blog.ovhcloud.com/wp-content/uploads/2020/08/88F1A300-DEB2-4708-8019-67FBC90E098F.png 651w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/88F1A300-DEB2-4708-8019-67FBC90E098F-300x166.png 300w" sizes="auto, (max-width: 326px) 100vw, 326px" /></figure></div>



<p>We need to be able guarantee that the deployments have no impact on what had worked previously, and that new features work as expected. That&#8217;s why we focus heavily on integration and functional tests. To write efficient and relevant tests, it&#8217;s necessary to use appropriate tooling. In our case, we need tools matching our needs:</p>



<ul class="wp-block-list"><li><strong>Automated tool chain</strong>. This is an obvious one; but automating tests is a huge time saver as it allows us to run them automatically on our continuous integration platform at every single change. It also helps us building an ever-growing suite of tests which act as a non-regression chain.</li><li><strong>Easy-to-launch integration tests</strong>. Making the integration tests easy-to-launch, even locally, makes the team more likely to actually launch them, update them, and write them as a safety net. Even tests that require multiple interacting services (databases, queues, external APIs) must be easy to launch.</li><li><strong>Easy-to-write integration tests</strong>. Developer experience is important, the team is more likely to write tests if it&#8217;s easy.</li></ul>



<h2 class="wp-block-heading">Testing at the appropriate scale</h2>



<p>In addition to regular unit tests, we run two kinds of API tests. This gives us the granularity and coverage we need for a safe deployment</p>



<p>At OVHcloud, the domain services are deployed as follows:</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" src="https://www.ovh.com/blog/wp-content/uploads/2020/08/0031660A-4143-42B9-91A9-F6977E7CDFF0.png" alt="Microservice architecture at OVHcloud" class="wp-image-19162" width="462" height="368" srcset="https://blog.ovhcloud.com/wp-content/uploads/2020/08/0031660A-4143-42B9-91A9-F6977E7CDFF0.png 924w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/0031660A-4143-42B9-91A9-F6977E7CDFF0-300x239.png 300w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/0031660A-4143-42B9-91A9-F6977E7CDFF0-768x611.png 768w" sizes="auto, (max-width: 462px) 100vw, 462px" /><figcaption>Microservice architecture at OVHcloud</figcaption></figure></div>



<p>The services communicate through a central HTTP gateway, whose role is to manage the routing of calls between services using HTTP headers and ensure security. Every single HTTP call between the services goes through the gateway.</p>



<p>As these services expose APIs through HTTP endpoints,&nbsp;<a href="https://en.wikipedia.org/wiki/API_testing" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">API testing</a> is the perfect way to test them. For this to work effectively, the services should be treated like <a href="https://en.wikipedia.org/wiki/Black-box_testing" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">black boxes</a> and the tests should only use their APIs. But, in reality, <a href="https://en.wikipedia.org/wiki/Gray_box_testing" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">grey box testing</a> is utilized. This is because we know the services implementation details, and we inject the datasets directly into the databases before testing.</p>



<p>As described in the diagram above, if we want to test the service <strong>Service 1</strong>, we require an environment with <strong>Gateway</strong> and potentially <strong>Service 2</strong> or&nbsp;<strong>Service 3</strong> to be available. This quickly becomes difficult to set up; especially if it is required for all the services to be tested.</p>



<p>So to test the API of a service, we need a way to isolate it from the others. This is what we will call <strong>isolated service tests&nbsp;</strong>in the rest of the blog post.</p>



<h3 class="wp-block-heading">Isolated service tests</h3>



<p>Isolated service tests are a kind of test between the unit test and the integration test. The service is started in a controlled environment, and its APIs are tested through various means.&nbsp;In isolated service tests, we allow for the following actions:</p>



<ul class="wp-block-list"><li>perform API calls or send events,</li><li>manipulate databases,</li><li>make assertions using:<ul><li>the responses to the API calls,</li><li>the events dispatched in queues,</li><li>direct queries on databases.</li></ul></li></ul>



<p>To do so, we launch the services with its technical dependencies (databases, queues, caches, etc) but we replace the HTTP gateway with an <strong>HTTP mock server</strong>. This approach helps us to avoid the deployment of other services and allows us to simply mock them.</p>



<p>Our tests are executed by a <strong>test runner</strong>. Before executing the actual tests, the role of the test runner is to populate the data of the environment:</p>



<ul class="wp-block-list"><li>databases are populated using the <strong>&#8220;clean, insert&#8221;</strong> strategy,</li><li>HTTP mocks are registered to the mock server.</li></ul>



<p>This allows us to focus our tests correctly. In order to test a service, we need to set the state of the database and external services responses.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="349" src="https://www.ovh.com/blog/wp-content/uploads/2020/08/26BBDD24-2B94-44F5-B254-3A09637D9219-1024x349.png" alt="Isolated service test workflow" class="wp-image-19164" srcset="https://blog.ovhcloud.com/wp-content/uploads/2020/08/26BBDD24-2B94-44F5-B254-3A09637D9219-1024x349.png 1024w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/26BBDD24-2B94-44F5-B254-3A09637D9219-300x102.png 300w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/26BBDD24-2B94-44F5-B254-3A09637D9219-768x262.png 768w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/26BBDD24-2B94-44F5-B254-3A09637D9219-1536x523.png 1536w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/26BBDD24-2B94-44F5-B254-3A09637D9219.png 1829w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Isolated service test workflow</figcaption></figure></div>



<p>These tests are automatically executed at each merge on the staging branch of a service, and they serve as functional non-regression tests.</p>



<p>While this method is useful, it is not sufficient. As the calls are mocked, they must be updated manually at each change of the services involved. Also the mocks may not strictly correspond to reality. This is why we couple it with more complete&nbsp;<strong>integration tests</strong>.</p>



<h3 class="wp-block-heading">Integration tests</h3>



<p>The goal of these tests is to deploy all the services managed by the Domain Names team in the same state as in production. We still use a HTTP mock server instead of the HTTP Gateway, because there are still some external services we want to be able to mock. But the services belonging to our team are not mocked, we deploy them and register them to the mock server as backends.</p>



<p>This way, we can connect all our services together, and mock only the calls made to external services.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="736" src="https://www.ovh.com/blog/wp-content/uploads/2020/08/BC9A4DE4-1BFB-4A63-9E6C-970FEB9D9F7C-1024x736.png" alt="Integration test workflow" class="wp-image-19167" srcset="https://blog.ovhcloud.com/wp-content/uploads/2020/08/BC9A4DE4-1BFB-4A63-9E6C-970FEB9D9F7C-1024x736.png 1024w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/BC9A4DE4-1BFB-4A63-9E6C-970FEB9D9F7C-300x216.png 300w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/BC9A4DE4-1BFB-4A63-9E6C-970FEB9D9F7C-768x552.png 768w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/BC9A4DE4-1BFB-4A63-9E6C-970FEB9D9F7C-1536x1104.png 1536w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/BC9A4DE4-1BFB-4A63-9E6C-970FEB9D9F7C.png 1588w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Integration test workflow</figcaption></figure></div>



<p>We use this to test complex workflows consisting of multiple calls made to different services. As a concrete example, it allows us to test the order funnel workflow by making the same calls that are made by the order funnel.</p>



<p>But unlike the isolated services tests, these are only executed once a day. This is because it requires deploying all our services in a short-lived environment, directly on a continuous integration platform &#8211; which may take a while.</p>



<h2 class="wp-block-heading">Executing the tests</h2>



<h3 class="wp-block-heading">Technical stack</h3>



<p>The method described above is generic, and can be applied using any tools you need. The abstract building blocks we need are:</p>



<ul class="wp-block-list"><li>a test runner,</li><li>an HTTP mock server,</li><li>a continuous integration platform.</li></ul>



<h4 class="wp-block-heading">Venom, a declarative test runner</h4>



<p><a href="https://github.com/ovh/venom" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Venom</a> is a declarative integration testing framework developed in-house at OVHcloud. Venom provides primitives to make HTTP calls, manipulate databases and message queues, and much more. It also provides a powerful context for writing assertions. This is completely optional though, simple shell scripts would work just fine, although they are less expressive and more complex to write.</p>



<p>With Venom, test suites are written in YAML. This makes the test suites easy to read and easy to store alongside the source code of the tested service. A test suite is just a sequence of test cases composed of multiple steps. The steps are actions executed sequentially on the service or its environment, on which we can perform assertions.</p>



<pre title="Example of a Venom test suite" class="wp-block-code"><code lang="yaml" class="language-yaml">name: Testing "Users" service
version: "2"
testcases:
    - name: Initialize database fixtures
      steps:
        - type: dbfixtures
          database: postgres
          dsn: "{{.postgres_dsn}}"
          migrations: ../../testdata/schemas
          folder: ../../testdata/fixtures
     
    - name: Try to retrieve data about user 313
      steps:
        - type: http
          method: GET
          url: "{{.service_url}}/api/v1/users/313"
          assertions:
            - result.statuscode ShouldEqual 200
            - result.bodyjson.id ShouldEqual 313
            - result.bodyjson.first_name ShouldEqual John
            - result.bodyjson.last_name ShouldEqual Doe
     
    - name: Try to update the name of user 313
      steps:
        # Perform the update
        - type: http
          method: PATCH
          url: "{{.service_url}}/api/v1/users/313"
          body: |
            {
              "first_name": "Jane",
              "last_name": "Smith"
            }
          assertions:
            - result.statuscode ShouldEqual 200
 
        # Check that the first name and last name were correctly updated
        - type: http
          method: GET
          url: "{{.service_url}}/api/v1/users/313"
          assertions:
            - result.statuscode ShouldEqual 200
            - result.bodyjson.id ShouldEqual 313
            - result.bodyjson.first_name ShouldEqual Jane
            - result.bodyjson.last_name ShouldEqual Smith</code></pre>



<p>The above test suite performs basic tests on a &#8220;Users&#8221; CRUD service. The test suite itself doesn&#8217;t start the service nor its dependencies, it assumes that they&#8217;re already started.</p>



<p>First, fixtures are loaded into the database. This is helpful to start testing most endpoints without having to manually register them through the API. Then, a few calls are performed and assertions are checked to ensure everything works as expected.</p>



<p>The killer feature of Venom is that it embeds a whole lot of executors that might be needed to test any service with arbitrary dependencies: raw scripts, HTTP, gRPC, SQL (MySQL and PostgreSQL), Redis, Kafka (producer and consumer), RabbitMQ, and even SMTP and IMAP to test out email sending!</p>



<h4 class="wp-block-heading">Smocker, a HTTP mock server</h4>



<p>As seen above, we need a server that can allow us to mock HTTP responses and simulate the behavior of a HTTP gateway.</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" src="https://www.ovh.com/blog/wp-content/uploads/2020/08/3E498F0D-0200-40D3-9846-9197E9CB3E3F.png" alt="smocker.dev" class="wp-image-19170" width="300" height="291" srcset="https://blog.ovhcloud.com/wp-content/uploads/2020/08/3E498F0D-0200-40D3-9846-9197E9CB3E3F.png 400w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/3E498F0D-0200-40D3-9846-9197E9CB3E3F-300x291.png 300w" sizes="auto, (max-width: 300px) 100vw, 300px" /><figcaption><a href="https://smocker.dev" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer">https://smocker.dev</a></figcaption></figure></div>



<p>Venom allows us to make assertions on the return values of HTTP calls and on the state of technical dependencies. But as it doesn&#8217;t provide the features we need alone, we fallback to an other tool, <a href="https://smocker.dev/" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Smocker</a>, developed for our use case. It features a user interface that is invaluable for writing mocks iteratively.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="512" src="https://www.ovh.com/blog/wp-content/uploads/2020/08/screenshot-history-1024x512.png" alt="" class="wp-image-19123" srcset="https://blog.ovhcloud.com/wp-content/uploads/2020/08/screenshot-history-1024x512.png 1024w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/screenshot-history-300x150.png 300w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/screenshot-history-768x384.png 768w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/screenshot-history.png 1400w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Smocker&#8217;s user interface</figcaption></figure></div>



<p>Thanks to Smocker, we can also perform a few more critical assertions on the internal behavior of our service:</p>



<ul class="wp-block-list"><li>assert that the correct endpoints are called,</li><li>assert that they&#8217;re called the right number of times,</li><li>assert that they&#8217;re called with the right payload.</li></ul>



<p>These features help us get a firmer grasp on the internals of the services we test, and help us to keep up with the evolution of the execution flow.</p>



<p>First, mocks must be registered to them via an API. A mock is simply a configuration file that initiates the sending of a given HTTP response when a specific call is made to an endpoint. The mock can have multiple filters; such as method, path, query parameters, etc. It also contains some contextual information; including the maximum number of calls on a route, response delay, etc.</p>



<pre title="Example of a Smocker mock" class="wp-block-code"><code lang="yaml" class="language-yaml">- request:
    method: GET
    path: /users/313
    headers:
      X-Service-Destination: users-service
  response:
    status: 200
    headers:
      Content-Type: application/json
    body: |
      {
        "id": 313,
        "first_name": "John",
        "last_name": "Doe"
      }</code></pre>



<p>Smocker can define mocks redirecting calls to another destination. This allows it to simulate the way the HTTP gateway works by defining the right mocks.</p>



<h4 class="wp-block-heading">CDS, a continuous integration platform</h4>



<p><a href="https://github.com/ovh/cds" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">CDS</a> (Continuous Delivery Service) is a full-featured continuous delivery and automation platform developed in-house at OVHcloud. It&#8217;s a powerful alternative to other existing platforms; such as Jenkins, Travis or GitLab-CI. CDS allows us to create complex execution workflows running in various environments (virtual machines, containers).</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" src="https://www.ovh.com/blog/wp-content/uploads/2019/02/cds-header.jpg" alt="CDS" class="wp-image-14628" width="600" height="300" srcset="https://blog.ovhcloud.com/wp-content/uploads/2019/02/cds-header.jpg 800w, https://blog.ovhcloud.com/wp-content/uploads/2019/02/cds-header-300x150.jpg 300w, https://blog.ovhcloud.com/wp-content/uploads/2019/02/cds-header-768x384.jpg 768w" sizes="auto, (max-width: 600px) 100vw, 600px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="595" src="https://www.ovh.com/blog/wp-content/uploads/2020/08/capture-start.gif" alt="" class="wp-image-19126"/><figcaption>CDS user interface</figcaption></figure></div>



<p>CDS provides a concept of requirements which we use extensively to instantiate the expected environment for running our tests.&nbsp;This feature allows us to quickly declare the technical services that we will need during tests execution&nbsp;(databases, queues, caches, etc). It is quite similar to the &#8220;services&#8221; section available in a Travis file, for example.</p>



<h3 class="wp-block-heading">Putting everything together</h3>



<p>The tests are stored alongside the source code of services generally following this hierarchy:</p>



<pre class="wp-block-preformatted">tests/
  venom/
    schemas/
      .sql
      ...
    fixtures/
      .yml
      ...
    mocks/
      test_suite.mocks.yml
    test_suite.yml<table></table></pre>



<p>For each service, the goal is to be able to launch the tests locally. The steps include:</p>



<ul class="wp-block-list"><li>set up technical dependencies (databases, caches, etc) and the mock server within Docker containers,</li><li>use variables in Venom tests files&nbsp;to be able to manipulate them with Venom (initialize data-sets, fill cache, etc),</li><li>designate the mock server as our HTTP gateway using environment variables at service launch,</li><li>fill Venom variables at test launch.</li></ul>



<p>A Venom test suite could look like this:</p>



<pre class="wp-block-code"><code lang="yaml" class="language-yaml">version: "2"
name: Contacts endpoints testsuite
testcases:
- name: Save a new contact successfully
  steps:
  - type: dbfixtures
    database: postgres
    dsn: "{{.pgsql_dsn}}"
    migrations: ../schemas
    folder: ../fixtures
  - type: http
    method: POST
    url: "{{.mock_server}}/reset"
    assertions:
     - result.statuscode ShouldEqual 200
  - type: http
    method: POST
    url: "{{.mock_server}}/mocks"
    bodyFile: ./mocks/create_contact_mocks.yaml
    assertions:
     - result.statuscode ShouldEqual 200
  - type: http
    method: POST
    headers:
      Content-Type: application/json
    url: "{{.my_app}}/contacts"
    bodyFile: contact_create.json
    assertions:
     - result.statuscode ShouldEqual 201</code></pre>



<p>Venom will:</p>



<ol class="wp-block-list"><li>initialize the database using the migration files and the fixtures available into&nbsp;<strong>/schemas</strong>&nbsp;and <strong>/fixtures</strong>,</li><li>reset the mock server,</li><li>set the mocks into Smocker (mock server) using the <strong>create_contact_mocks</strong><strong><code>.yml</code></strong>file,</li><li>call the service using <strong>contact_create.json</strong>&nbsp;file as payload, and make assertions on the result.</li></ol>



<p>To launch this test, all we need is to define at launch these Venom variables:</p>



<ul class="wp-block-list"><li><strong>pgsql_dsn</strong>: connection URL to the Postgres database,</li><li><strong>mock_server</strong>: administration URL of the mock server,</li><li><strong>my_app</strong>: URL of the service to test.</li></ul>



<p>These variables are automatically set up within the Makefile of the service.</p>



<p>Launching functional tests locally allows us to debug our services step by step, and in a coherent context. As the datasets are controlled, it is quite easy to reproduce the errors and build efficient non-regression suites.</p>



<p>Once committed and merged on the staging branch, these tests are executed automatically by CDS. It works quite similarly to the local execution except that it is CDS and not a script that will set up the technical dependencies. The service is also launched as a container, using an image built in a previous job.</p>



<p>As indicated above, the technical dependencies, as well as the service, are declared as a service in the requirement part of the CDS job.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="553" src="https://www.ovh.com/blog/wp-content/uploads/2020/08/requirements-1024x553.png" alt="" class="wp-image-19129" srcset="https://blog.ovhcloud.com/wp-content/uploads/2020/08/requirements-1024x553.png 1024w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/requirements-300x162.png 300w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/requirements-768x415.png 768w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/requirements-1536x829.png 1536w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/requirements-2048x1106.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>This allows to fill in CDS, the Venom variables mentioned above like this:</p>



<ul class="wp-block-list"><li><strong>pgsql_dsn</strong>: postgres://myuser:password@postgres/venom?sslmode=disable (user, password and database are set using options on requirement)</li><li><strong>mock_server</strong>: http://mockserver:8081 (default admin port on smocker)</li><li><strong>my_app</strong>: http://myapp:8080 (default service port)</li></ul>



<p>Thanks to Venom&#8217;s command line, the only remaining thing to do in the pipeline is to execute the tests.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="911" height="216" src="https://www.ovh.com/blog/wp-content/uploads/2020/08/workflow-domain.png" alt="" class="wp-image-19128" srcset="https://blog.ovhcloud.com/wp-content/uploads/2020/08/workflow-domain.png 911w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/workflow-domain-300x71.png 300w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/workflow-domain-768x182.png 768w" sizes="auto, (max-width: 911px) 100vw, 911px" /></figure></div>



<p>The testing pipeline is included in each of our workflows, and the deployment in production is necessarily blocked if any of the tests fail.</p>



<h2 class="wp-block-heading">Retrospective</h2>



<p>While setting up these integration tests, we faced some difficulties:</p>



<ul class="wp-block-list"><li><strong>The time to production was longer</strong>. Integration tests being executed before any deployment prevented us from deploying hotfixes instantaneously, they have to run through the integration tests beforehand. This is even worse if a hotfix breaks an integration test. Fortunately, in this case, it is possible to manually force the deployment through CDS.</li><li><strong>Integration tests are often quite complicated to maintain</strong>. But the YAML format of the tests and mocks allow us to comment to explain the content of these, which facilitates maintainability.</li></ul>



<p>Aside from this, the <strong>overall experience with this testing method is extremely positive</strong>.</p>



<p>It adds an <strong>additional safety net</strong> to ensure the functional behavior of services as non-regression tests. Moreover, it allows us to be able to <strong>test new functionalities in advance</strong>, over several services, through updated mocks. And finally, it greatly <strong>eases reproducing functional bugs</strong> and debugging them.</p>



<p>The cost often associated with integration tests can be off-putting, but the implementation can easily be done incrementally on a service-by-service basis.</p>



<p>To go even further, we are now thinking of making several improvements.</p>



<h3 class="wp-block-heading">Code coverage</h3>



<p>Our micro-services are mainly written in <a href="https://golang.org/" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Go</a>. Go makes it possible to build a test binary &#8211; including a code coverage profile. This can be used in addition to Venom tests to generate the coverage of integration tests.</p>



<p>Code coverage is a nice-to-have metric as it enables you to detect sections of code that are less tested.</p>



<h3 class="wp-block-heading">Documentation generation</h3>



<p>Because Smocker, the HTTP mock server, is central to networking between the services, it has the ability to <a href="https://smocker.dev/screenshots/screenshot-history-visualize.png" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">generate sequence diagrams</a> describing the behavior of each call. This can be used to dynamically generate some sections of our internal documentation.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="512" src="https://www.ovh.com/blog/wp-content/uploads/2020/08/screenshot-history-visualize-1024x512.png" alt="" class="wp-image-19130" srcset="https://blog.ovhcloud.com/wp-content/uploads/2020/08/screenshot-history-visualize-1024x512.png 1024w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/screenshot-history-visualize-300x150.png 300w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/screenshot-history-visualize-768x384.png 768w, https://blog.ovhcloud.com/wp-content/uploads/2020/08/screenshot-history-visualize.png 1400w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Sequence diagram generated by Smocker</figcaption></figure></div>
<img loading="lazy" decoding="async" src="//blog.ovhcloud.com/wp-content/plugins/matomo/app/matomo.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fblog.ovhcloud.com%2Fdeclarative-integration-tests-in-a-microservice-environment%2F&amp;action_name=Declarative%20integration%20tests%20in%20a%20microservice%20environment&amp;urlref=https%3A%2F%2Fblog.ovhcloud.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
