<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Verrazzano Enterprise Container Platform – Verrazzano Application Traits</title>
    <link>/docs/applications/oam/traits/</link>
    <description>Recent content in Verrazzano Application Traits on Verrazzano Enterprise Container Platform</description>
    <generator>Hugo -- gohugo.io</generator>
    
	  <atom:link href="/docs/applications/oam/traits/index.xml" rel="self" type="application/rss+xml" />
    
    
      
        
      
    
    
    <item>
      <title>Docs: About Verrazzano Traits</title>
      <link>/docs/applications/oam/traits/about-traits/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/docs/applications/oam/traits/about-traits/</guid>
      <description>
        
        
        &lt;p&gt;Traits customize Component workloads and generate related resources during deployment.
Verrazzano provides several Traits, for example IngressTrait and MetricsTrait.
The platform extracts Traits contained within an ApplicationConfiguration during deployment.
This processing is similar to the extraction of workload content from Component resources.
Note that for some Kubernetes resources, the &lt;code&gt;oam-kubernetes-runtime&lt;/code&gt; operator may need to be granted &lt;code&gt;create&lt;/code&gt; permission.&lt;/p&gt;
&lt;p&gt;A Kubernetes operator, for example &lt;code&gt;verrazzano-application-operator&lt;/code&gt;, processes these extracted Traits and may create additional related resources or may alter related workloads.
Each Trait implementation will behave differently.&lt;/p&gt;
&lt;p&gt;The following sample shows an IngressTrait applied to a referenced Component.
&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; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;apiVersion&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;core.oam.dev/v1alpha2&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;kind&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;ApplicationConfiguration&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;spec&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;components&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;    &lt;/span&gt;- &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;componentName&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;example-component&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;traits&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;        &lt;/span&gt;- &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;trait&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;apiVersion&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;oam.verrazzano.io/v1alpha1&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;kind&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;IngressTrait&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;spec&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;              &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;rules&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;                &lt;/span&gt;- &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;paths&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;                    &lt;/span&gt;- &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;path&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;/greet&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&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;Each Trait type optionally can have an associated TraitDefinition.
This provides the platform with additional information about the Trait&amp;rsquo;s schema and workloads to which the Trait can be applied.
A TraitDefintion is typically provided by the platform, not an end user.&lt;/p&gt;
&lt;p&gt;The Verrazzano platform provides several Trait definitions and implementations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../../../../docs/applications/oam/traits/ingress/ingress/&#34;&gt;IngressTrait&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../../../docs/applications/oam/traits/metrics/metrics/&#34;&gt;MetricsTrait&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../../../docs/applications/oam/traits/logging/logging/&#34;&gt;LoggingTrait&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Docs: IngressTrait</title>
      <link>/docs/applications/oam/traits/ingress/ingress/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/docs/applications/oam/traits/ingress/ingress/</guid>
      <description>
        
        
        &lt;p&gt;The &lt;a href=&#34;../../../../docs/reference/vao-oam-v1alpha1/#oam.verrazzano.io/v1alpha1.IngressTrait&#34;&gt;IngressTrait&lt;/a&gt; custom resource contains the configuration of host and path rules for traffic routing to an application.  Here is a sample ApplicationConfiguration that specifies an IngressTrait.  To deploy an example application that demonstrates this IngressTrait, see &lt;a href=&#34;../../../../docs/examples/hello-helidon/&#34;&gt;Hello World Helidon&lt;/a&gt;.&lt;/p&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&gt;&lt;code&gt;apiVersion: core.oam.dev/v1alpha2
kind: ApplicationConfiguration
metadata:
  name: hello-helidon-appconf
  namespace: hello-helidon
  annotations:
    version: v1.0.0
    description: &amp;quot;Hello Helidon application&amp;quot;
spec:
  components:
    - componentName: hello-helidon-component
      traits:
        - trait:
            apiVersion: oam.verrazzano.io/v1alpha1
            kind: IngressTrait
            metadata:
              name: hello-helidon-ingress
            spec:
              rules:
                - paths:
                    - path: &amp;quot;/greet&amp;quot;
                      pathType: Prefix
&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;In the sample configuration, the IngressTrait &lt;code&gt;hello-helidon-ingress&lt;/code&gt; is set on the &lt;code&gt;hello-helidon-component&lt;/code&gt; application component and defines an ingress rule that configures a path and path type.  This exposes a route for external access to the application.  Note that because no &lt;code&gt;hosts&lt;/code&gt; list is given for the &lt;a href=&#34;#ingressrule&#34;&gt;IngressRule&lt;/a&gt;, a DNS host name is automatically generated.&lt;/p&gt;
&lt;p&gt;For example, with the sample application configuration successfully deployed, the application will be accessible with the &lt;code&gt;path&lt;/code&gt; specified in the IngressTrait and the generated host name.&lt;/p&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&gt;&lt;code&gt;$ HOST=$(kubectl get gateways.networking.istio.io hello-helidon-hello-helidon-gw -n hello-helidon -o jsonpath={.spec.servers[0].hosts[0]})
$ echo $HOST
hello-helidon-appconf.hello-helidon.11.22.33.44.nip.io

$ curl -sk -X GET https://${HOST}/greet
&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;Load balancer session affinity is configured using an HTTP cookie in a destination rule. Here is an updated sample ApplicationConfiguration that includes a destination rule with an HTTP cookie.&lt;/p&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&gt;&lt;code&gt;apiVersion: core.oam.dev/v1alpha2
kind: ApplicationConfiguration
metadata:
  name: hello-helidon-appconf
  namespace: hello-helidon
  annotations:
    version: v1.0.0
    description: &amp;quot;Hello Helidon application&amp;quot;
spec:
  components:
    - componentName: hello-helidon-component
      traits:
        - trait:
            apiVersion: oam.verrazzano.io/v1alpha1
            kind: IngressTrait
            metadata:
              name: hello-helidon-ingress
            spec:
              rules:
                - paths:
                    - path: &amp;quot;/greet&amp;quot;
                      pathType: Prefix
                - destination:
                    httpCookie:
                      name: sessioncookie
                      path: &amp;quot;/&amp;quot;
                      ttl: 600
&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;Additionally, an authorization policy limiting access to specific request principals and optionally predicated on additional conditions, can be specified for a path.  Request for the path will be limited to matching request principals that meet the defined conditions, otherwise the request will be denied.&lt;/p&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&gt;&lt;code&gt;apiVersion: core.oam.dev/v1alpha2
kind: ApplicationConfiguration
metadata:
  name: hello-helidon-appconf
  namespace: hello-helidon
  annotations:
    version: v1.0.0
    description: &amp;quot;Hello Helidon application&amp;quot;
spec:
  components:
    - componentName: hello-helidon-component
      traits:
        - trait:
            apiVersion: oam.verrazzano.io/v1alpha1
            kind: IngressTrait
            metadata:
              name: hello-helidon-ingress
            spec:
              rules:
                - paths:
                    - path: &amp;quot;/greet&amp;quot;
                      pathType: Prefix
                      authorizationPolicy:
                        rules:
                          - from:
                              requestPrincipals:
                                - &amp;quot;*&amp;quot;
                              when:
                                - key: request.auth.claims[realm_access][roles]
                                  values:
                                    - &amp;quot;customer&amp;quot;
&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;Use the following rules related to the host name:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you provide a host name, then you have an option to provide a certificate.  If you do not provide a certificate, then Verrazzano generates one for you.&lt;/li&gt;
&lt;li&gt;If you provide a certificate, the TLS secret for that certificate must be in the &lt;code&gt;istio-system&lt;/code&gt; namespace.&lt;/li&gt;
&lt;li&gt;If you provide a certificate, then you must provide a host name.&lt;/li&gt;
&lt;li&gt;If you do not provide either a host name or a certificate, then Verrazzano generates them for you.&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Docs: LoggingTrait</title>
      <link>/docs/applications/oam/traits/logging/logging/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/docs/applications/oam/traits/logging/logging/</guid>
      <description>
        
        
        &lt;p&gt;The &lt;a href=&#34;../../../../docs/reference/vao-oam-v1alpha1/#oam.verrazzano.io/v1alpha1.LoggingTrait&#34;&gt;LoggingTrait&lt;/a&gt; custom resource contains the configuration for an additional logging sidecar with a custom image and Fluentd configuration file.
Here is a sample ApplicationConfiguration that includes a LoggingTrait.
To deploy an example application with this LoggingTrait, replace the ApplicationConfiguration of the &lt;a href=&#34;../../../../docs/examples/wls-coh/todo-list/&#34;&gt;ToDo-List&lt;/a&gt; example application with the following sample.&lt;/p&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&gt;&lt;code&gt;apiVersion: core.oam.dev/v1alpha2
kind: ApplicationConfiguration
metadata:
  name: todo-appconf
  namespace: todo-list
  annotations:
    version: v1.0.0
    description: &amp;quot;ToDo List example application&amp;quot;
spec:
  components:
    - componentName: todo-domain
      traits:
        - trait:
            apiVersion: oam.verrazzano.io/v1alpha1
            kind: LoggingTrait
            metadata:
              name: logging-trait-example
              namespace: todo-list
            spec:
              loggingImage: fluent/fleuntd-example-image # Replace with custom Fluentd Image
              loggingConfig: |-
                # Replace with Fluentd config file
                &amp;lt;match **&amp;gt;
                @type stdout
                &amp;lt;/match&amp;gt;
    - componentName: todo-jdbc-configmap
    - componentName: todo-mysql-configmap
    - componentName: todo-mysql-service
    - componentName: todo-mysql-deployment
&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;In this sample configuration, the LoggingTrait &lt;code&gt;logging-trait-example&lt;/code&gt; is set on the &lt;code&gt;todo-domain&lt;/code&gt; application component and defines a logging sidecar with the given Fluentd image and configuration file.
This sidecar will be attached to the component&amp;rsquo;s pod and will gather logs according to the given Fluentd configuration file.
In order for the Fluentd DaemonSet to collect the custom logs, the Fluentd configuration file needs to direct the logs to &lt;code&gt;STDOUT&lt;/code&gt;, as demonstrated in the previous example.&lt;/p&gt;
&lt;p&gt;For example, when the &lt;a href=&#34;../../../../docs/examples/wls-coh/todo-list/&#34;&gt;ToDo-List&lt;/a&gt; example ApplicationConfiguration is successfully deployed with a LoggingTrait, the &lt;code&gt;tododomain-adminserver&lt;/code&gt; pod will have a container named &lt;code&gt;logging-stdout&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&gt;&lt;code&gt;$ kubectl get pods tododomain-adminserver -n todo-list -o jsonpath=&#39;{.spec.containers[*].name}&#39;
  ... logging-stdout ...
&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;In this example, the &lt;code&gt;logging-stdout&lt;/code&gt; container will run the image given in the LoggingTrait and a ConfigMap named &lt;code&gt;logging-stdout-todo-domain-domain&lt;/code&gt; will be created with the custom Fluentd configuration file.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Docs: MetricsTrait</title>
      <link>/docs/applications/oam/traits/metrics/metrics/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/docs/applications/oam/traits/metrics/metrics/</guid>
      <description>
        
        
        &lt;p&gt;The &lt;a href=&#34;../../../../docs/reference/vao-oam-v1alpha1/#oam.verrazzano.io/v1alpha1.MetricsTrait&#34;&gt;MetricsTrait&lt;/a&gt; custom resource contains the configuration information needed to enable metrics for an application component.  Component workloads configured with a MetricsTrait are set up to emit metrics through an endpoint that are scraped by a given Prometheus deployment.  Here is a sample ApplicationConfiguration that specifies a MetricsTrait.  To deploy an example application that demonstrates a MetricsTrait, see &lt;a href=&#34;../../../../docs/examples/hello-helidon/&#34;&gt;Hello World Helidon&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note that if an ApplicationConfiguration does not specify a MetricsTrait, then a default MetricsTrait will be generated with values appropriate for the workload type.&lt;/p&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&gt;&lt;code&gt;apiVersion: core.oam.dev/v1alpha2
kind: ApplicationConfiguration
metadata:
  name: hello-helidon-appconf
  namespace: hello-helidon
  annotations:
    version: v1.0.0
    description: &amp;quot;Hello Helidon application&amp;quot;
spec:
  components:
    - componentName: hello-helidon-component
      traits:
        - trait:
            apiVersion: oam.verrazzano.io/v1alpha1
            kind: MetricsTrait
        - trait:
            apiVersion: oam.verrazzano.io/v1alpha1
            kind: IngressTrait
            metadata:
              name: hello-helidon-ingress
            spec:
              rules:
                - paths:
                    - path: &amp;quot;/greet&amp;quot;
                      pathType: Prefix
&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;In the sample configuration, a MetricsTrait is specified for the &lt;code&gt;hello-helidon-component&lt;/code&gt; application component.&lt;/p&gt;
&lt;p&gt;With the sample application configuration successfully deployed, you can query for metrics from the application component.
&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&gt;&lt;code&gt;$ HOST=$(kubectl get ingress \
     -n verrazzano-system vmi-system-prometheus \
     -o jsonpath={.spec.rules[0].host})
$ echo $HOST

prometheus.vmi.system.default.&amp;lt;ip&amp;gt;.nip.io

$ VZPASS=$(kubectl get secret \
     --namespace verrazzano-system verrazzano \
     -o jsonpath={.data.password} | base64 \
     --decode; echo)
$ curl -sk \
    --user verrazzano:${VZPASS} \
    -X GET https://${HOST}/api/v1/query?query=vendor_requests_count_total

{&amp;quot;status&amp;quot;:&amp;quot;success&amp;quot;,&amp;quot;data&amp;quot;:{&amp;quot;resultType&amp;quot;:&amp;quot;vector&amp;quot;,&amp;quot;result&amp;quot;:[{&amp;quot;metric&amp;quot;:{&amp;quot;__name__&amp;quot;:&amp;quot;vendor_requests_count_total&amp;quot;,&amp;quot;app&amp;quot;:&amp;quot;hello-helidon&amp;quot;,&amp;quot;app_oam_dev_component&amp;quot;:&amp;quot;hello-helidon-component&amp;quot;,&amp;quot;app_oam_dev_name&amp;quot;:&amp;quot;hello-helidon-appconf&amp;quot;,&amp;quot;app_oam_dev_resourceType&amp;quot;:&amp;quot;WORKLOAD&amp;quot;,&amp;quot;app_oam_dev_revision&amp;quot;:&amp;quot;hello-helidon-component-v1&amp;quot;,&amp;quot;containerizedworkload_oam_crossplane_io&amp;quot;:&amp;quot;496df78f-ef8b-4753-97fd-d9218d2f38f1&amp;quot;,&amp;quot;job&amp;quot;:&amp;quot;hello-helidon-appconf_default_helidon-logging_hello-helidon-component&amp;quot;,&amp;quot;namespace&amp;quot;:&amp;quot;helidon-logging&amp;quot;,&amp;quot;pod_name&amp;quot;:&amp;quot;hello-helidon-workload-b7d9d95d8-ht7gb&amp;quot;,&amp;quot;pod_template_hash&amp;quot;:&amp;quot;b7d9d95d8&amp;quot;},&amp;quot;value&amp;quot;:[1616535232.487,&amp;quot;4800&amp;quot;]}]}}
&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;

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