<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Verrazzano Enterprise Container Platform – Observability</title>
    <link>/docs/observability/</link>
    <description>Recent content in Observability on Verrazzano Enterprise Container Platform</description>
    <generator>Hugo -- gohugo.io</generator>
    
	  <atom:link href="/docs/observability/index.xml" rel="self" type="application/rss+xml" />
    
    
      
        
      
    
    
    <item>
      <title>Docs: Monitoring</title>
      <link>/docs/observability/monitoring/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/docs/observability/monitoring/</guid>
      <description>
        
        
        
      </description>
    </item>
    
    <item>
      <title>Docs: Logging</title>
      <link>/docs/observability/logging/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/docs/observability/logging/</guid>
      <description>
        
        
        
      </description>
    </item>
    
    <item>
      <title>Docs: Tracing Application Requests</title>
      <link>/docs/observability/tracing/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/docs/observability/tracing/</guid>
      <description>
        
        
        
      </description>
    </item>
    
    <item>
      <title>Docs: Customize Persistent Storage</title>
      <link>/docs/observability/storage/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/docs/observability/storage/</guid>
      <description>
        
        
        &lt;p&gt;The following components can use persistent storage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OpenSearch&lt;/li&gt;
&lt;li&gt;OpenSearch Dashboards&lt;/li&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;Grafana&lt;/li&gt;
&lt;li&gt;Keycloak/MySQL&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By default, each Verrazzano installation profile has different storage characteristics.  The &lt;code&gt;dev&lt;/code&gt; profile uses ephemeral
storage only, but in all other profiles, each of the listed components use persistent storage.  For more information, see &lt;a href=&#34;../../docs/setup/install/perform/profiles/#profile-configurations&#34;&gt;Profile Configurations&lt;/a&gt;.&lt;/p&gt;


&lt;div class=&#34;alert alert-danger&#34; role=&#34;alert&#34;&gt;
&lt;h4 class=&#34;alert-heading&#34;&gt;NOTE&lt;/h4&gt;

    Ephemeral storage is not recommended for use in production; Kubernetes pods can be restarted at any time, leading to
a loss of data and system instability if non-persistent storage is used.  Persistent storage is recommended
for all use cases beyond evaluation or development.

&lt;/div&gt;

&lt;p&gt;While each profile has its own default persistence settings, in each case you have the option to override the profile
defaults to customize your persistence settings.&lt;/p&gt;
&lt;p&gt;You can customize the persistence settings for these components through the
&lt;a href=&#34;../../docs/reference/vpo-verrazzano-v1beta1/#install.verrazzano.io/v1beta1.VerrazzanoSpec&#34;&gt;VerrazzanoSpec&lt;/a&gt;, as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Overriding the persistence settings for all components (Keycloak, Grafana, Prometheus, OpenSearch, and OpenSearch Dashboards) by using the &lt;code&gt;defaultVolumeSource&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;Overriding the persistence settings for Keycloak by using the &lt;code&gt;volumeSource&lt;/code&gt; field on that component&amp;rsquo;s configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can set the global &lt;code&gt;defaultVolumeSource&lt;/code&gt; and component-level &lt;code&gt;volumeSource&lt;/code&gt; fields to one of the following values:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Storage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://kubernetes.io/docs/concepts/storage/volumes/#emptydir&#34;&gt;&lt;code&gt;emptyDir&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;Ephemeral storage; should not be used for production scenarios.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24
/#persistentvolumeclaimvolumesource-v1-core&#34;&gt;&lt;code&gt;persistentVolumeClaim&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;A &lt;code&gt;PersistentVolumeClaimVolumeSource&lt;/code&gt; where the &lt;code&gt;claimSource&lt;/code&gt; field references a named &lt;code&gt;volumeClaimSpecTemplate&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;When you want to use a &lt;code&gt;persistentVolumeClaim&lt;/code&gt; to override the storage settings for components, you must do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a &lt;a href=&#34;../../docs/reference/vpo-verrazzano-v1beta1/#install.verrazzano.io/v1beta1.VolumeClaimSpecTemplate&#34;&gt;volumeClaimSpecTemplate&lt;/a&gt; which identifies
the desired persistence settings.&lt;/li&gt;
&lt;li&gt;Configure a &lt;code&gt;persistentVolumeClaim&lt;/code&gt; for the component where the &lt;code&gt;claimName&lt;/code&gt; field references the template you created previously.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This lets you create named persistence settings that can be shared across multiple components within a Verrazzano
configuration.  Note that the existence of a persistence template in the &lt;code&gt;volumeClaimSpecTemplates&lt;/code&gt; list does not
directly result in the creation of a persistent volume, or affect any component storage settings until it is referenced
by either &lt;code&gt;defaultVolumeSource&lt;/code&gt; or a specific component&amp;rsquo;s &lt;code&gt;volumeSource&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;examples&#34;&gt;Examples&lt;/h2&gt;
&lt;p&gt;Review the following customizing persistent storage examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#customize-persistence-globally-using-defaultvolumesource&#34;&gt;Customize persistence globally using defaultVolumeSource&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#customize-persistentvolumeclaim-settings-for-keycloak-using-volumesource&#34;&gt;Customize PersistentVolumeClaim settings for Keycloak using volumeSource&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#use-global-and-local-persistence-settings-together&#34;&gt;Use global and local persistence settings together&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;customize-persistence-globally-using-defaultvolumesource&#34;&gt;Customize persistence globally using defaultVolumeSource&lt;/h3&gt;


&lt;div class=&#34;alert alert-primary&#34; role=&#34;alert&#34;&gt;
&lt;h4 class=&#34;alert-heading&#34;&gt;NOTE&lt;/h4&gt;

    Beginning in version 1.5, persistent storage is always required for MySQL. If &lt;code&gt;defaultVolumeSource&lt;/code&gt; is configured to use &lt;code&gt;emptyDir&lt;/code&gt;, then MySQL will ignore that configuration setting.

&lt;/div&gt;

&lt;p&gt;If &lt;code&gt;defaultVolumeSource&lt;/code&gt; is configured, then that setting will be used for all components that require storage.&lt;/p&gt;
&lt;p&gt;For example, the following Verrazzano configuration uses the &lt;code&gt;prod&lt;/code&gt; profile, but disables persistent storage for all components.
&lt;style type=&#34;text/css&#34;&gt;
    code {
        margin: 0;
        padding: 0;
    }

    .copy-code-button {
        position: absolute;
        right: 0;
        top: -29px;
        font-size: 12px;
        line-height: 14px;
        width: 65px;
        color: white;
        background-color: #30638E;
        border: 1px solid #30638E;
        white-space: nowrap;
        padding: 6px 6px 7px 6px;
    }

    .copy-code-button:hover,
    .copy-code-button:focus{
        background-color: gray;
        opacity: 1;
    }

&lt;/style&gt;

&lt;div class=&#34;clipboard&#34;&gt;
    &lt;div class=&#34;highlight&#34;&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;apiVersion: install.verrazzano.io/v1beta1
kind: Verrazzano
metadata:
  name: no-storage-prod
spec:
  profile: prod
  defaultVolumeSource:
      emptyDir: {}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;
    function createCopyButton(highlightDiv) {
        const button = document.createElement(&#34;button&#34;);
        button.innerText = &#34;Copy&#34;;
        button.className = &#34;copy-code-button&#34;;
        button.addEventListener(&#34;click&#34;, () =&gt;
            copyCodeToClipboard(button, highlightDiv)
        );
        addCopyButton(button, highlightDiv);
    }

    function addCopyButton(button, highlightDiv) {
        highlightDiv.insertBefore(button, highlightDiv.firstChild);
        const wrapper = document.createElement(&#34;div&#34;);
        highlightDiv.parentNode.insertBefore(wrapper, highlightDiv);
        wrapper.appendChild(highlightDiv);
    }

    async function copyCodeToClipboard(button, highlightDiv) {
        let codeToCopy = highlightDiv.querySelector(&#34;:last-child &gt; code, pre&#34;).innerText;
        
        let codeBlock = codeToCopy.split(&#34;\n&#34;);
        let expectedLine = codeBlock.findIndex(line =&gt; line.toLowerCase().startsWith(&#34;# expected response&#34;) || line.toLowerCase().startsWith(&#34;# sample output&#34;));
        if (expectedLine !== -1) {
            codeBlock.splice(expectedLine);
        }
        codeToCopy = codeBlock.join(&#34;\n&#34;);
        
        codeToCopy = codeToCopy.replace(/^#(.*)$/gm, &#39;&#39;).trim();
        
        codeToCopy = codeToCopy.replace(/\$\s+/gm, &#39;&#39;).trim();
        codeToCopy = codeToCopy.replace(/\n{2,}/g,&#39;\n&#39;);
        console.log(codeToCopy);
        try {
            await navigator.clipboard.writeText(codeToCopy);
        } catch (err) {
            
            const textarea = document.createElement(&#39;textarea&#39;);
            textarea.value = codeToCopy;
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand(&#39;copy&#39;);
            textarea.remove();
        }
        button.blur();
        button.innerText = &#34;Copied&#34;;
        setTimeout(function () {
            button.innerText = &#34;Copy&#34;;
        }, 2000);
    }


    document
        .querySelectorAll(&#34;.highlight&#34;)
        .forEach((highlightDiv) =&gt; createCopyButton(highlightDiv));
&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;The following example uses &lt;code&gt;persistentVolumeClaim&lt;/code&gt; to override persistence settings globally for a &lt;code&gt;prod&lt;/code&gt; profile, to use
&lt;code&gt;100Gi&lt;/code&gt; volumes for all components, instead of the default of &lt;code&gt;50Gi&lt;/code&gt;.
&lt;style type=&#34;text/css&#34;&gt;
    code {
        margin: 0;
        padding: 0;
    }

    .copy-code-button {
        position: absolute;
        right: 0;
        top: -29px;
        font-size: 12px;
        line-height: 14px;
        width: 65px;
        color: white;
        background-color: #30638E;
        border: 1px solid #30638E;
        white-space: nowrap;
        padding: 6px 6px 7px 6px;
    }

    .copy-code-button:hover,
    .copy-code-button:focus{
        background-color: gray;
        opacity: 1;
    }

&lt;/style&gt;

&lt;div class=&#34;clipboard&#34;&gt;
    &lt;div class=&#34;highlight&#34;&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;apiVersion: install.verrazzano.io/v1beta1
kind: Verrazzano
metadata:
  name: prod-global-override
spec:
  profile: prod
  defaultVolumeSource:
    persistentVolumeClaim:
      claimName: globalOverride
  volumeClaimSpecTemplates:
    - metadata:
        name: globalOverride
      spec:
        resources:
          requests:
            storage: 100Gi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;
    function createCopyButton(highlightDiv) {
        const button = document.createElement(&#34;button&#34;);
        button.innerText = &#34;Copy&#34;;
        button.className = &#34;copy-code-button&#34;;
        button.addEventListener(&#34;click&#34;, () =&gt;
            copyCodeToClipboard(button, highlightDiv)
        );
        addCopyButton(button, highlightDiv);
    }

    function addCopyButton(button, highlightDiv) {
        highlightDiv.insertBefore(button, highlightDiv.firstChild);
        const wrapper = document.createElement(&#34;div&#34;);
        highlightDiv.parentNode.insertBefore(wrapper, highlightDiv);
        wrapper.appendChild(highlightDiv);
    }

    async function copyCodeToClipboard(button, highlightDiv) {
        let codeToCopy = highlightDiv.querySelector(&#34;:last-child &gt; code, pre&#34;).innerText;
        
        let codeBlock = codeToCopy.split(&#34;\n&#34;);
        let expectedLine = codeBlock.findIndex(line =&gt; line.toLowerCase().startsWith(&#34;# expected response&#34;) || line.toLowerCase().startsWith(&#34;# sample output&#34;));
        if (expectedLine !== -1) {
            codeBlock.splice(expectedLine);
        }
        codeToCopy = codeBlock.join(&#34;\n&#34;);
        
        codeToCopy = codeToCopy.replace(/^#(.*)$/gm, &#39;&#39;).trim();
        
        codeToCopy = codeToCopy.replace(/\$\s+/gm, &#39;&#39;).trim();
        codeToCopy = codeToCopy.replace(/\n{2,}/g,&#39;\n&#39;);
        console.log(codeToCopy);
        try {
            await navigator.clipboard.writeText(codeToCopy);
        } catch (err) {
            
            const textarea = document.createElement(&#39;textarea&#39;);
            textarea.value = codeToCopy;
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand(&#39;copy&#39;);
            textarea.remove();
        }
        button.blur();
        button.innerText = &#34;Copied&#34;;
        setTimeout(function () {
            button.innerText = &#34;Copy&#34;;
        }, 2000);
    }


    document
        .querySelectorAll(&#34;.highlight&#34;)
        .forEach((highlightDiv) =&gt; createCopyButton(highlightDiv));
&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;The following example uses a &lt;code&gt;managed-cluster&lt;/code&gt; profile but overrides the persistence settings to use ephemeral storage.
&lt;style type=&#34;text/css&#34;&gt;
    code {
        margin: 0;
        padding: 0;
    }

    .copy-code-button {
        position: absolute;
        right: 0;
        top: -29px;
        font-size: 12px;
        line-height: 14px;
        width: 65px;
        color: white;
        background-color: #30638E;
        border: 1px solid #30638E;
        white-space: nowrap;
        padding: 6px 6px 7px 6px;
    }

    .copy-code-button:hover,
    .copy-code-button:focus{
        background-color: gray;
        opacity: 1;
    }

&lt;/style&gt;

&lt;div class=&#34;clipboard&#34;&gt;
    &lt;div class=&#34;highlight&#34;&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;apiVersion: install.verrazzano.io/v1beta1
kind: Verrazzano
metadata:
  name: mgdcluster-empty-storage-example
spec:
  profile: managed-cluster
  defaultVolumeSource:
    emptyDir: {}  # Use emphemeral storage for all Components unless overridden
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;
    function createCopyButton(highlightDiv) {
        const button = document.createElement(&#34;button&#34;);
        button.innerText = &#34;Copy&#34;;
        button.className = &#34;copy-code-button&#34;;
        button.addEventListener(&#34;click&#34;, () =&gt;
            copyCodeToClipboard(button, highlightDiv)
        );
        addCopyButton(button, highlightDiv);
    }

    function addCopyButton(button, highlightDiv) {
        highlightDiv.insertBefore(button, highlightDiv.firstChild);
        const wrapper = document.createElement(&#34;div&#34;);
        highlightDiv.parentNode.insertBefore(wrapper, highlightDiv);
        wrapper.appendChild(highlightDiv);
    }

    async function copyCodeToClipboard(button, highlightDiv) {
        let codeToCopy = highlightDiv.querySelector(&#34;:last-child &gt; code, pre&#34;).innerText;
        
        let codeBlock = codeToCopy.split(&#34;\n&#34;);
        let expectedLine = codeBlock.findIndex(line =&gt; line.toLowerCase().startsWith(&#34;# expected response&#34;) || line.toLowerCase().startsWith(&#34;# sample output&#34;));
        if (expectedLine !== -1) {
            codeBlock.splice(expectedLine);
        }
        codeToCopy = codeBlock.join(&#34;\n&#34;);
        
        codeToCopy = codeToCopy.replace(/^#(.*)$/gm, &#39;&#39;).trim();
        
        codeToCopy = codeToCopy.replace(/\$\s+/gm, &#39;&#39;).trim();
        codeToCopy = codeToCopy.replace(/\n{2,}/g,&#39;\n&#39;);
        console.log(codeToCopy);
        try {
            await navigator.clipboard.writeText(codeToCopy);
        } catch (err) {
            
            const textarea = document.createElement(&#39;textarea&#39;);
            textarea.value = codeToCopy;
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand(&#39;copy&#39;);
            textarea.remove();
        }
        button.blur();
        button.innerText = &#34;Copied&#34;;
        setTimeout(function () {
            button.innerText = &#34;Copy&#34;;
        }, 2000);
    }


    document
        .querySelectorAll(&#34;.highlight&#34;)
        .forEach((highlightDiv) =&gt; createCopyButton(highlightDiv));
&lt;/script&gt;&lt;/p&gt;
&lt;h3 id=&#34;customize-persistentvolumeclaim-settings-for-keycloak-using-volumesource&#34;&gt;Customize PersistentVolumeClaim settings for Keycloak using volumeSource&lt;/h3&gt;
&lt;p&gt;The following example Verrazzano configuration enables a &lt;code&gt;100Gi&lt;/code&gt; PersistentVolumeClaim for the MySQL component in Keycloak
in a &lt;code&gt;dev&lt;/code&gt; profile configuration.  This overrides the default of ephemeral storage for Keycloak in that profile, while
retaining the default storage settings for other components.
&lt;style type=&#34;text/css&#34;&gt;
    code {
        margin: 0;
        padding: 0;
    }

    .copy-code-button {
        position: absolute;
        right: 0;
        top: -29px;
        font-size: 12px;
        line-height: 14px;
        width: 65px;
        color: white;
        background-color: #30638E;
        border: 1px solid #30638E;
        white-space: nowrap;
        padding: 6px 6px 7px 6px;
    }

    .copy-code-button:hover,
    .copy-code-button:focus{
        background-color: gray;
        opacity: 1;
    }

&lt;/style&gt;

&lt;div class=&#34;clipboard&#34;&gt;
    &lt;div class=&#34;highlight&#34;&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;apiVersion: install.verrazzano.io/v1beta1
kind: Verrazzano
metadata:
  name: dev-mysql-storage-example
spec:
  profile: dev
  components:
    keycloak:
      mysql:
        volumeSource:
          persistentVolumeClaim:
            claimName: mysql  # Use the &amp;#34;mysql&amp;#34; PVC template for the MySQL volume configuration
  volumeClaimSpecTemplates:
  - metadata:
      name: mysql      
    spec:
      resources:
        requests:
          storage: 100Gi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;
    function createCopyButton(highlightDiv) {
        const button = document.createElement(&#34;button&#34;);
        button.innerText = &#34;Copy&#34;;
        button.className = &#34;copy-code-button&#34;;
        button.addEventListener(&#34;click&#34;, () =&gt;
            copyCodeToClipboard(button, highlightDiv)
        );
        addCopyButton(button, highlightDiv);
    }

    function addCopyButton(button, highlightDiv) {
        highlightDiv.insertBefore(button, highlightDiv.firstChild);
        const wrapper = document.createElement(&#34;div&#34;);
        highlightDiv.parentNode.insertBefore(wrapper, highlightDiv);
        wrapper.appendChild(highlightDiv);
    }

    async function copyCodeToClipboard(button, highlightDiv) {
        let codeToCopy = highlightDiv.querySelector(&#34;:last-child &gt; code, pre&#34;).innerText;
        
        let codeBlock = codeToCopy.split(&#34;\n&#34;);
        let expectedLine = codeBlock.findIndex(line =&gt; line.toLowerCase().startsWith(&#34;# expected response&#34;) || line.toLowerCase().startsWith(&#34;# sample output&#34;));
        if (expectedLine !== -1) {
            codeBlock.splice(expectedLine);
        }
        codeToCopy = codeBlock.join(&#34;\n&#34;);
        
        codeToCopy = codeToCopy.replace(/^#(.*)$/gm, &#39;&#39;).trim();
        
        codeToCopy = codeToCopy.replace(/\$\s+/gm, &#39;&#39;).trim();
        codeToCopy = codeToCopy.replace(/\n{2,}/g,&#39;\n&#39;);
        console.log(codeToCopy);
        try {
            await navigator.clipboard.writeText(codeToCopy);
        } catch (err) {
            
            const textarea = document.createElement(&#39;textarea&#39;);
            textarea.value = codeToCopy;
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand(&#39;copy&#39;);
            textarea.remove();
        }
        button.blur();
        button.innerText = &#34;Copied&#34;;
        setTimeout(function () {
            button.innerText = &#34;Copy&#34;;
        }, 2000);
    }


    document
        .querySelectorAll(&#34;.highlight&#34;)
        .forEach((highlightDiv) =&gt; createCopyButton(highlightDiv));
&lt;/script&gt;&lt;/p&gt;
&lt;h3 id=&#34;use-global-and-local-persistence-settings-together&#34;&gt;Use global and local persistence settings together&lt;/h3&gt;
&lt;p&gt;The following example uses a &lt;code&gt;dev&lt;/code&gt; installation profile, but overrides the profile persistence settings to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;200Gi&lt;/code&gt; volumes for all components by default.&lt;/li&gt;
&lt;li&gt;Use a &lt;code&gt;100Gi&lt;/code&gt; volume for the MySQL instance associated with Keycloak.&lt;/li&gt;
&lt;/ul&gt;
&lt;style type=&#34;text/css&#34;&gt;
    code {
        margin: 0;
        padding: 0;
    }

    .copy-code-button {
        position: absolute;
        right: 0;
        top: -29px;
        font-size: 12px;
        line-height: 14px;
        width: 65px;
        color: white;
        background-color: #30638E;
        border: 1px solid #30638E;
        white-space: nowrap;
        padding: 6px 6px 7px 6px;
    }

    .copy-code-button:hover,
    .copy-code-button:focus{
        background-color: gray;
        opacity: 1;
    }

&lt;/style&gt;

&lt;div class=&#34;clipboard&#34;&gt;
    &lt;div class=&#34;highlight&#34;&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;apiVersion: install.verrazzano.io/v1beta1
kind: Verrazzano
metadata:
  name: dev-storage-example
spec:
  profile: dev
  defaultVolumeSource:
    persistentVolumeClaim:
      claimName: vmi     # Set storage globally for the metrics stack
  components:
    keycloak:
      mysql:
        volumeSource:
          persistentVolumeClaim:
            claimName: mysql  # Set storage separately for keycloak&amp;#39;s MySql instance
  volumeClaimSpecTemplates:
    - metadata:
        name: mysql
      spec:
        resources:
          requests:
            storage: 100Gi
    - metadata:
        name: vmi
      spec:
        resources:
          requests:
            storage: 200Gi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;
    function createCopyButton(highlightDiv) {
        const button = document.createElement(&#34;button&#34;);
        button.innerText = &#34;Copy&#34;;
        button.className = &#34;copy-code-button&#34;;
        button.addEventListener(&#34;click&#34;, () =&gt;
            copyCodeToClipboard(button, highlightDiv)
        );
        addCopyButton(button, highlightDiv);
    }

    function addCopyButton(button, highlightDiv) {
        highlightDiv.insertBefore(button, highlightDiv.firstChild);
        const wrapper = document.createElement(&#34;div&#34;);
        highlightDiv.parentNode.insertBefore(wrapper, highlightDiv);
        wrapper.appendChild(highlightDiv);
    }

    async function copyCodeToClipboard(button, highlightDiv) {
        let codeToCopy = highlightDiv.querySelector(&#34;:last-child &gt; code, pre&#34;).innerText;
        
        let codeBlock = codeToCopy.split(&#34;\n&#34;);
        let expectedLine = codeBlock.findIndex(line =&gt; line.toLowerCase().startsWith(&#34;# expected response&#34;) || line.toLowerCase().startsWith(&#34;# sample output&#34;));
        if (expectedLine !== -1) {
            codeBlock.splice(expectedLine);
        }
        codeToCopy = codeBlock.join(&#34;\n&#34;);
        
        codeToCopy = codeToCopy.replace(/^#(.*)$/gm, &#39;&#39;).trim();
        
        codeToCopy = codeToCopy.replace(/\$\s+/gm, &#39;&#39;).trim();
        codeToCopy = codeToCopy.replace(/\n{2,}/g,&#39;\n&#39;);
        console.log(codeToCopy);
        try {
            await navigator.clipboard.writeText(codeToCopy);
        } catch (err) {
            
            const textarea = document.createElement(&#39;textarea&#39;);
            textarea.value = codeToCopy;
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand(&#39;copy&#39;);
            textarea.remove();
        }
        button.blur();
        button.innerText = &#34;Copied&#34;;
        setTimeout(function () {
            button.innerText = &#34;Copy&#34;;
        }, 2000);
    }


    document
        .querySelectorAll(&#34;.highlight&#34;)
        .forEach((highlightDiv) =&gt; createCopyButton(highlightDiv));
&lt;/script&gt;

      </description>
    </item>
    
  </channel>
</rss>
