<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vedant Shrotria</title>
    <description>The latest articles on DEV Community by Vedant Shrotria (@jonsy13).</description>
    <link>https://dev.to/jonsy13</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F415007%2F19e1d8e6-508b-44e6-a39e-567381d047e9.jpg</url>
      <title>DEV Community: Vedant Shrotria</title>
      <link>https://dev.to/jonsy13</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonsy13"/>
    <language>en</language>
    <item>
      <title>Logging using EFK for LitmusChaos</title>
      <dc:creator>Vedant Shrotria</dc:creator>
      <pubDate>Tue, 05 Jul 2022 12:58:10 +0000</pubDate>
      <link>https://dev.to/litmus-chaos/logging-using-efk-for-chaoscenter-5gp6</link>
      <guid>https://dev.to/litmus-chaos/logging-using-efk-for-chaoscenter-5gp6</guid>
      <description>&lt;p&gt;Hi Folks!!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In this article, we are going to discuss how we can set up logging using the EFK stack (Elastic-Search+FluentD+Kibana) for Litmuschaos experiments.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Firstly we will be doing a standard EFK setup on our k8s cluster and then we will see what filters we can use for fetching logs of a particular experiment run.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you already have the EFK setup in your cluster which can fetch logs for all pods (or at least logs of pods in the Agent namespace), then you can skip to the logs filtering part through Kibana UI.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  let us look at the components in this stack -
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Elasticsearch&lt;/strong&gt; is a real-time, distributed, and scalable search engine which allows for full-text and structured search, as well as for analytics. We will be using ElasticSearch for storing, filtering, and indexing our logs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kibana&lt;/strong&gt; is a powerful data visualization frontend and dashboard for Elasticsearch. Kibana allows us to explore our Elasticsearch log data through a web interface, and build dashboards and queries to quickly answer questions and gain insight into your Kubernetes applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FluentD&lt;/strong&gt; is a popular open-source data collector, that can be used to tail container log files, filter and transform the log data, and deliver it to the Elasticsearch cluster, where it can be indexed and stored.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpn12hiv5ymi7tas9r8k.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpn12hiv5ymi7tas9r8k.gif" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay Okay, no more theory, without any further waiting let’s jump into it!!&lt;/p&gt;

&lt;h2&gt;
  
  
  EFK Stack configuration steps
&lt;/h2&gt;

&lt;p&gt;The required manifests for fluentd and updated values.yml according to 7.17.1 version of ElasticSearch and Kibana are available &lt;a href="https://github.com/Jonsy13/EFK-Setup" rel="noopener noreferrer"&gt;here&lt;/a&gt; for reference.&lt;/p&gt;

&lt;p&gt;For making sure while we are trying to implement this setup, we are using the same version as this blog, we can go ahead and clone the provided repository.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com:Jonsy13/EFK-Setup.git
cd EFK-Setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Creating separate namespaces for EFK setup
&lt;/h3&gt;

&lt;p&gt;It’s generally a good practice to have the application deployed in separate namespaces that have different concerns concerning functionalities and behavior.&lt;/p&gt;

&lt;p&gt;In our case, we are creating different namespaces for EFK to separate the setup from Litmus components so that we can reduce the risk of disaster to our EFK setup. We will be installing Kibana and ElasticSearch in elastic-kibana namespace and Fluentd in fluentd namespace.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create ns elastic-kibana 
kubectl create ns fluentd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Installing Elasticsearch cluster for data/logs for indexing and storage
&lt;/h3&gt;

&lt;p&gt;We will be using the official helm chart for installing Elasticsearch.&lt;br&gt;
Firstly, we will have to add Elastic helm repo using the below command&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo add elastic https://helm.elastic.co
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy29ou344mx4pbwkiev69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy29ou344mx4pbwkiev69.png" width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we can install the ElasticSearch using above added helm repository as below&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ElasticSearch
helm install — values values.yaml elasticsearch elastic/elasticsearch -n elastic-kibana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tpmsawr0zrj9bpbpdwi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tpmsawr0zrj9bpbpdwi.png" width="800" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For verifying the successful installation, we can check pods of our elastic-search cluster -&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods -n elastic-kibana — selector=”app=elasticsearch-master”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Just after the installation, you might find the output of the above command below -&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6vw59wu1qrwvovm6qgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6vw59wu1qrwvovm6qgb.png" width="800" height="113"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can take some time for all pods to come in a ready state, as there is a Readiness probe configured for all pods of elastic-search cluster for configuration of the cluster.&lt;/p&gt;

&lt;p&gt;Once the Readiness probe finishes and gets satisfied, all the pods will come in a Ready state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmn4f6sza490odzptr1r0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmn4f6sza490odzptr1r0.png" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing Kibana for checking/filtering logs using Web Interface
&lt;/h3&gt;

&lt;p&gt;The above-provided official elastic helm repository, we added earlier also provides a chart for Kibana. So, we will use the official chart to install Kibana using the below command&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd Kibana
helm install — values values.yaml kibana elastic/kibana -n elastic-kibana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3rjma0d3jw18qj2766e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3rjma0d3jw18qj2766e.png" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For verifying the successful installation, we can go ahead and check if all kibana resources are created successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4ojr4hrgx3ggpbmz0st.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4ojr4hrgx3ggpbmz0st.png" width="800" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing FluentD for fetching logs, indexing, and storing
&lt;/h3&gt;

&lt;p&gt;We will be installing FluentD as a Daemonset so that we can get logs for all pods scheduled on different nodes from the &lt;code&gt;/var/log/&lt;/code&gt; directory mounted on all the nodes.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd FluentD
kubectl apply -f ./
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1qph8mdxp9fwf8dc366.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1qph8mdxp9fwf8dc366.png" width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are 3 files present in FluentD directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Jonsy13/EFK-Setup/blob/main/FluentD/manifest.yml" rel="noopener noreferrer"&gt;manifest.yml&lt;/a&gt;&lt;/strong&gt; — Manifest for deploying fluentd as daemonset, fetching logs from nodes, and exporting them to elasticsearch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Jonsy13/EFK-Setup/blob/main/FluentD/rbac.yaml" rel="noopener noreferrer"&gt;rbac.yml&lt;/a&gt;&lt;/strong&gt;— Manifest for applying clusterRole, ClusterRoleBinding, and Service Account for fluentD.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Jonsy13/EFK-Setup/blob/main/FluentD/config-map.yaml" rel="noopener noreferrer"&gt;config-map.yml&lt;/a&gt;&lt;/strong&gt; — This configmap contains a configuration file for fluentD as its data which is mounted in all pods of the fluentD daemonset.&lt;/p&gt;

&lt;p&gt;If we look at the data, we can see that we are adding an index_name to our logs which are getting filtered through this configuration file as fluentd-k8s. This index_name will be used for making our logs unique for filtering sources in Kibana UI.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  index_name fluentd-k8s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Complete configmap is available &lt;a href="https://github.com/Jonsy13/EFK-Setup/blob/main/FluentD/config-map.yaml" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessing Logs on Kibana Web Interface
&lt;/h2&gt;

&lt;p&gt;Now, with the current setup, fluentD will be fetching logs from all nodes and sending them to ElasticSearch. Now, for visualizing the stored logs from ElasticSearch, we will be using Kibana UI. So, Let’s open Kibana UI and check what are we getting there!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nm51kyhou1d2x1tk7l7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nm51kyhou1d2x1tk7l7.gif" width="306" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we open Kibana for the first time, we will be presented with a Welcome screen as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvr42z1dlf7awnwgpnol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvr42z1dlf7awnwgpnol.png" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since we already have our Elastic-Search setup, we don’t have to go for adding any new integrations. We can click on &lt;code&gt;Explore on my own&lt;/code&gt; button for moving forward to the Homepage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1yfl8qrbx21yzd3a523.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1yfl8qrbx21yzd3a523.png" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we want to explore the logs that we are getting from ElasticSearch, we will have to create an index pattern to identify the logs which we want to explore. (You may want to only explore only some parts of logs according to the use case).&lt;/p&gt;

&lt;p&gt;Let’s click on Discover Card and create an index pattern. After clicking on the Discover card, you will get a screen as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2For9y1o52mu179eseb106.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2For9y1o52mu179eseb106.png" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can take some time for ElasticSearch to get filled up the logs. Once there are some logs available in ElasticSearch, we can proceed further and click on create index pattern button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjs0bd9bjizxufteamr1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjs0bd9bjizxufteamr1.png" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above screen, we can add a pattern for identifying our logs. I have added the pattern as &lt;code&gt;fluentd-k8s*&lt;/code&gt; as we had the same tag added in the fluentd configuration for filtration. On the right side, if your added index pattern matches a source coming from ElasticSearch then it will also show us &lt;code&gt;Your index pattern matches 1 source&lt;/code&gt;, which means that Kibana can match the pattern with logs and filter them out.&lt;/p&gt;

&lt;p&gt;After adding the Name, we can click on &lt;code&gt;create index pattern&lt;/code&gt; button for saving it. After saving the pattern, it will show you what are the different fields, that we can get from the log details in the table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsajxlnxjrnp42pzj70kk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsajxlnxjrnp42pzj70kk.png" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, once we have added our index pattern, we can click on &lt;code&gt;Discover&lt;/code&gt; button in the sidebar for seeing the logs we are getting from ElasticSearch based on our index pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwla9c6p2n9sf7c5ucsx8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwla9c6p2n9sf7c5ucsx8.png" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, as we can see that we are getting logs for all the available pods. But we want to filter logs for fetching logs for specific pods, for that we will be using label filters.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Agent Plane Components pod logs&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We have 5 components which are part of agent plane, lets look at the required filters for all of them one by one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;chaos-operator —&lt;/strong&gt;
For chaos-operator, we can use below label as filter 
&lt;code&gt;kubernetes.labels.app.kubernetes.io/component=operator&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qamu3h1sbla6k37wwrh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qamu3h1sbla6k37wwrh.png" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;chaos-exporter —&lt;/strong&gt;
For chaos-exporter, we can use below label as filter
&lt;code&gt;kubernetes.labels.app=chaos-exporter&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1z2ap2h5elmmgwiassol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1z2ap2h5elmmgwiassol.png" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;subscriber —&lt;/strong&gt; 
For subscriber, we can use below label as filter
&lt;code&gt;kubernetes.labels.app=subscriber&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fad6y7g24i4v37slyam9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fad6y7g24i4v37slyam9j.png" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;event-tracker —&lt;/strong&gt;
For event-tracker, we can use below label as filter
&lt;code&gt;kubernetes.labels.app=event-tracker&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fscg4t2ujbgvz86jkjwrq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fscg4t2ujbgvz86jkjwrq.png" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;workflow-controller —&lt;/strong&gt;
For workflow-controller, we can use below label as filter
&lt;code&gt;kubernetes.labels.app=workflow-controller&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8lq9xb079svfe9o4w5f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8lq9xb079svfe9o4w5f.png" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiment pods logs —
&lt;/h3&gt;

&lt;p&gt;So, for experiment run, All the experiment related pods for that particular run are labeled with a unique chaosUID i.e. &lt;code&gt;kubernetes.labels.chaosUID&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, how will you get the value of this label?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well, once an experiment is completed, We can get &lt;code&gt;chaosUID&lt;/code&gt; of that experiment run from the chaos results tab as can be seen below image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo49ezlec9wr3mjn1vjy9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo49ezlec9wr3mjn1vjy9.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, using this label &lt;code&gt;kubernetes.labels.chaosUID&lt;/code&gt; , we will be able to get logs for that experiment run. But it will be giving combined logs of experiment, runner and helper with this one label only as all chaos pods related to one experiment run are labelled with this label. but we want to distinguish between experiment, runner and helper pods logs also, right?&lt;/p&gt;

&lt;p&gt;We will have to use one more labels which will be unique to particular Experiment pod, Runner pod &amp;amp; Helper pod. Let’s see how to achieve this.&lt;/p&gt;

&lt;p&gt;For Experiment pod logs, we can use the below labels —&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    1. kubernetes.labels.chaosUID: &amp;lt;chaosUID&amp;gt;

    2. kubernetes.labels.name: &amp;lt;experiment_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Runner pod logs, we can use below labels -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    1. kubernetes.labels.chaosUID: &amp;lt;chaosUID&amp;gt;

    2. kubernetes.labels.app_kubernetes_io/component: ”chaos-runner”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Helper pod logs, we can use the below labels -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    1. kubernetes.labels.chaosUID: &amp;lt;chaosUID&amp;gt;

    2. kubernetes.labels.name: &amp;lt;experiment-name&amp;gt;-helper-*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s take an example of a pod-network-loss experiment,&lt;/p&gt;

&lt;p&gt;In my case, the chaosUID is &lt;strong&gt;839d4a33–8e3a-4df5-b05a-2d136160c90d&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, for filtering logs of only the experiment pod, we will use these 2 labels -&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. kubernetes.labels.chaosUID: 839d4a33–8e3a-4df5-b05a-2d136160c90d

2. kubernetes.labels.name: pod-network-loss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq63vdie490jmga41njgy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq63vdie490jmga41njgy.png" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For filtering logs of only helper pod, we will use these 2 labels -&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. kubernetes.labels.chaosUID: 839d4a33–8e3a-4df5-b05a-2d136160c90d

2. kubernetes.labels.name: pod-network-loss-helper-*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5jp8tt5qjeymerhbqay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5jp8tt5qjeymerhbqay.png" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For filtering logs of only the runner pod, we will use these 2 labels -&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. kubernetes.labels.chaosUID: 839d4a33–8e3a-4df5-b05a-2d136160c90d
2. kubernetes.labels.app_kubernetes_io/component: ”chaos-runner”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ized9useyimk4a4nd6h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ized9useyimk4a4nd6h.png" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, as we can see now we can index our logs with a tag, store them in ElasticSearch and view &amp;amp; filter them on Kibana.&lt;/p&gt;

&lt;p&gt;Well, this was my first try with EFK and that’s all I got to know about it’s working. Will be writing more as I get to work more on this. Thanks for checking this blog out!!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Feel free to check out our ongoing project — &lt;a href="https://github.com/litmuschaos/litmus/tree/master/litmus-portal" rel="noopener noreferrer"&gt;Chaos Center&lt;/a&gt; and do let us know if you have any suggestions or feedback regarding the same. You can always submit a PR if you find any required changes.&lt;/p&gt;

&lt;p&gt;Make sure to reach out to us if you have any feedback or queries. Hope you found the blog informative!&lt;/p&gt;

&lt;p&gt;If chaos engineering is something that excites you or if you want to know more about cloud-native chaos engineering, don’t forget to check out our &lt;a href="https://litmuschaos.io/" rel="noopener noreferrer"&gt;LitmusChaos website&lt;/a&gt;, &lt;a href="https://hub.litmuschaos.io/" rel="noopener noreferrer"&gt;ChaosHub&lt;/a&gt;, and the &lt;a href="https://github.com/litmuschaos/litmus" rel="noopener noreferrer"&gt;LitmusChaos repo&lt;/a&gt;. Do leave a star if you find it insightful. 😊&lt;/p&gt;

&lt;p&gt;I would love to invite you to our community to stay connected with us and get your Chaos Engineering doubts cleared.&lt;br&gt;
To join our slack please follow the following steps!&lt;/p&gt;

&lt;p&gt;Step 1: Join the Kubernetes slack using the following link: &lt;a href="https://slack.k8s.io/" rel="noopener noreferrer"&gt;https://slack.k8s.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 2: Join the #litmus channel on the Kubernetes slack or use this link after joining the Kubernetes slack: &lt;a href="https://slack.litmuschaos.io/](https://slack.litmuschaos.io/)" rel="noopener noreferrer"&gt;https://slack.litmuschaos.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>elasticsearch</category>
      <category>litmuschaos</category>
      <category>logging</category>
    </item>
    <item>
      <title>E2E Dashboard at LitmusChaos</title>
      <dc:creator>Vedant Shrotria</dc:creator>
      <pubDate>Thu, 09 Jun 2022 12:27:58 +0000</pubDate>
      <link>https://dev.to/litmus-chaos/e2e-dashboard-at-litmuschaos-241o</link>
      <guid>https://dev.to/litmus-chaos/e2e-dashboard-at-litmuschaos-241o</guid>
      <description>&lt;p&gt;&lt;em&gt;In this article, we are going to discuss the dashboard we use for tracking our e2e-testing pipelines and how it is integrated with github-action pipelines.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Even before starting with the functionalities, you can check out the dashboard &lt;a href="https://litmuschaos.github.io/litmus-e2e/dashboard/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Firstly, why do we need an E2E dashboard? Isn’t the github actions showing everything we needed or were there some more requirements that we had apart from what github actions offer?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8ca813cly86k9rni6ty.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8ca813cly86k9rni6ty.gif" alt="Thinking" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, when we started, we had just 2–3 pipelines with which it was easy to go through different pipeline runs and check how our nightly pipelines are working or what is the test coverage of our pipelines. But now when we have around 12–15 pipelines, it became difficult to understand the behavior of pipelines just by looking at some of the latest runs. As the main purpose of all pipelines is to help us understand our builds, find out issues before they happen, or find them as soon as possible even after release so that they can be fixed at the earliest. You can’t afford a bug that was added last month to be in the current month’s pipeline as debugging the same can take a very long time.&lt;/p&gt;

&lt;p&gt;Now, the answer to all the above problems was to have some type of dashboard through which we can see the historical data of our pipelines whether it is nightly built or manually builds before release candidates or on-demand run. We wanted to see all the details like logs of the pipeline, name of pipeline run, last commit in the repository &amp;amp; the tag of LitmusChaos with which particular pipeline ran, Verdict of the pipeline, steps in the pipeline, etc. Having all these details in one place in UI as a dashboard would help us to have transparency between the developers as well as for checking the health of our product before any release candidate making us more confident in our product.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How is the progress going?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Okay no more waiting, Let’s have a walk-through of the dashboard and its different functionalities.&lt;/p&gt;

&lt;p&gt;Firstly, let’s talk about the Homepage, which gives the Gods-Eye look at all the E2E pipelines. This screen contains all the pipelines (Manual &amp;amp; Nightly) along with their current status, last running timestamp &amp;amp; name of the repository where that pipeline is running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fht3w3711bg1b8mgvc1lj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fht3w3711bg1b8mgvc1lj.png" alt="Dashboard Homepage" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The header contains buttons for navigating to only manual runs and nightly runs. This helps to distinguish between manual &amp;amp; nightly runs.&lt;/p&gt;

&lt;p&gt;Nightly pipelines are running on daily basis automatically so that we can check status of all builds daily without having to manually trigger the pipelines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7wv8o3zcxhf4m3pp91he.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7wv8o3zcxhf4m3pp91he.png" alt="Nightly pipelines" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Manual runs are done before/after release for checking the health of release builds and also in cases when we want to run E2E manually for testing any feature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwl4v4wr6plg85hk4vho2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwl4v4wr6plg85hk4vho2.png" alt="Manual pipelines" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Deep dive into a Pipeline&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When we click on &lt;strong&gt;Go to details&lt;/strong&gt; on a particular pipeline card, It will navigate us to a new screen showing pipeline runs of that particular pipeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9uly2m86gjxtk9ria59y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9uly2m86gjxtk9ria59y.png" alt="Pipeline Card" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib2qrl3rmje886p7siuf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib2qrl3rmje886p7siuf.png" alt="Pipeline runs" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above screen, we can see the overall test coverage as well as see historical data of that particular pipeline. The tables show the pipeline-run ID, last running time, description (showing the last commit of the repository after which the pipeline was run), and Pipeline status.&lt;/p&gt;

&lt;p&gt;If we click on a pipeline run id in the table, It will open a side modal showing pipeline details like jobs, steps running as part of jobs, the status of jobs, the status of steps, and the total time taken for that particular pipeline run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0adc89npizuo72q4ksj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0adc89npizuo72q4ksj.png" alt="Pipeline run details" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking on a Job will show steps running as part of that Job.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2rearpvavxecvulur3u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2rearpvavxecvulur3u.png" alt="Job details" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For checking the logs of a step, we can click on a step name and it will expand and shows logs for that step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5dcj4np2f4chpnkmfk4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5dcj4np2f4chpnkmfk4.png" alt="Step logs" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, as we can see that this dashboard provides us everything in one place that we need to check status/health of our product. If we look at the tech-stack of this dashboard, The frontend is implemented using React JS &amp;amp; backend is implemented using Golang. The source code for the same is available &lt;a href="https://github.com/litmuschaos/litmus-e2e/tree/dashboard" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are still some of the functionalities that are needed such as graphical UI for visualising historical data of pipelines, slack notifications/alerts &amp;amp; many more like this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Feel free to check out our ongoing project — &lt;a href="https://github.com/litmuschaos/litmus/tree/master/litmus-portal" rel="noopener noreferrer"&gt;Chaos Center&lt;/a&gt; and do let us know if you have any suggestions or feedback regarding the same. You can always submit a PR if you find any required changes.&lt;/p&gt;

&lt;p&gt;Make sure to reach out to us if you have any feedback or queries. Hope you found the blog informative!&lt;/p&gt;

&lt;p&gt;If chaos engineering is something that excites you or if you want to know more about cloud-native chaos engineering, don’t forget to check out our &lt;a href="https://litmuschaos.io/" rel="noopener noreferrer"&gt;LitmusChaos website&lt;/a&gt;, &lt;a href="https://hub.litmuschaos.io/" rel="noopener noreferrer"&gt;ChaosHub&lt;/a&gt;, and the &lt;a href="https://github.com/litmuschaos/litmus" rel="noopener noreferrer"&gt;LitmusChaos repo&lt;/a&gt;. Do leave a star if you find it insightful. 😊&lt;/p&gt;

&lt;p&gt;I would love to invite you to our community to stay connected with us and get your Chaos Engineering doubts cleared.&lt;br&gt;
To join our slack please follow the following steps!&lt;/p&gt;

&lt;p&gt;Step 1: Join the Kubernetes slack using the following link: &lt;a href="https://slack.k8s.io/" rel="noopener noreferrer"&gt;https://slack.k8s.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 2: Join the #litmus channel on the Kubernetes slack or use this link after joining the Kubernetes slack: &lt;a href="https://slack.litmuschaos.io/" rel="noopener noreferrer"&gt;https://slack.litmuschaos.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>testing</category>
      <category>automation</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Cloud Native Application &amp; Testing Automation</title>
      <dc:creator>Vedant Shrotria</dc:creator>
      <pubDate>Mon, 14 Mar 2022 09:19:09 +0000</pubDate>
      <link>https://dev.to/litmus-chaos/cloud-native-application-testing-automation-2bh5</link>
      <guid>https://dev.to/litmus-chaos/cloud-native-application-testing-automation-2bh5</guid>
      <description>&lt;p&gt;&lt;em&gt;Hi Folks!!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In this article, we are going to discuss how we can create an automated pipeline using Github-Actions for a cloud-native application &amp;amp; use Cypress for testing the same.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you are not much familiar with Cypress, you can also check my previous blog on &lt;a href="https://dev.to/litmus-chaos/cypress-end-to-end-testing-and-experience-cn4"&gt;End-To-End Testing Using Cypress&lt;/a&gt; for the same.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Okay, before starting with automation &amp;amp; pipeline, let's talk about some of the things that should be considered while choosing an environment for testing...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6s1p53omvedit1k7zpnn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6s1p53omvedit1k7zpnn.gif" alt="Feel it" width="498" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. How does your application work &amp;amp; what are the resources it needs to be fully functional?
&lt;/h3&gt;

&lt;p&gt;Here, we should think about how our application works as well as its functionalities. Well, the reason for this is that Your application can be cloud-native/monolithic &amp;amp; we might be able to run the same using docker/docker-compose or using k8s cluster as well.&lt;/p&gt;

&lt;p&gt;If we can't run that application using docker/docker-compose, we need to look into the Kubernetes testing tools available.&lt;/p&gt;

&lt;p&gt;In our case, ChaosCenter is a cloud-native application and also there is a chaos-agent component, which needs to run as a part of a k8s cluster. Simulation/Mocking of functionality is good for unit/integration testing, for end-to-end testing, we should try to have our testing environment as realistic as possible. &lt;/p&gt;

&lt;p&gt;As we are planning more on the E2E testing and our application is also cloud-native, we chose to have a Kubernetes cluster on which we can deploy our application.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The testing environment will be transient or always running &amp;amp; which tool to use for provisioning the same?
&lt;/h3&gt;

&lt;p&gt;Well, having a test environment that is always running helps to debug issues faster in the pipeline but at the same time as &lt;strong&gt;it is always running, it will be more costly.&lt;/strong&gt; That cost can also be reduced by using spot instances on cloud providers like AWS. ( If you are using them :-) ) &lt;/p&gt;

&lt;p&gt;On the other side, if we automate the creation/deletion of the test environment as a part of the pipeline, it helps us to reduce the cost automatically, but at the same time, we have to pay in terms of time consumed for creation/deletion of our environment. Here, when we talk about debugging efforts, so yes we can create another pipeline that will automate the creation of the environment as well as testing but won't tear down the setup so that we can do debugging later and delete the environment manually.&lt;/p&gt;

&lt;p&gt;With the above considerations, We finalized that we will be using a transient k8s cluster as our test environment. There are many tools like &lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;Minikube&lt;/a&gt;, &lt;a href="https://kind.sigs.k8s.io/docs/user/quick-start/" rel="noopener noreferrer"&gt;KIND&lt;/a&gt;, &lt;a href="https://k3s.io/" rel="noopener noreferrer"&gt;K3s&lt;/a&gt;, &lt;a href="https://k3d.io/" rel="noopener noreferrer"&gt;K3D&lt;/a&gt; &amp;amp; many others which can be used as per requirements/use-case. In case you are using cloud providers, Tools like eksctl, gcloud, az, Terraform, Ansible &amp;amp; many other tools can also be used for the same.&lt;/p&gt;

&lt;p&gt;After analyzing some of the tools mentioned above, we chose to go with K3d. The main reason behind choosing K3d is that we can create Loadbalancer services very easily in the K3d cluster without any extra configuration, Which on another side also allows us to have Ingress configuration as realistic as possible like cloud providers. This helped us when we wanted to test our application over loadBalancer &amp;amp; Ingress.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyp4zzc99x61p3evp4yf5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyp4zzc99x61p3evp4yf5.gif" alt="Waiting" width="498" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Okay okay, No more theory let's jump into steps....&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Automation of Creation/Deletion of Clusters
&lt;/h2&gt;

&lt;p&gt;As we discussed above, we don't want to have our testing cluster always running. So we need to automate the same as part of our pipeline.&lt;/p&gt;

&lt;p&gt;As we are using Github-Actions workflows, K3d already has its GitHub-Action &lt;a href="https://github.com/AbsaOSS/k3d-action" rel="noopener noreferrer"&gt;AbsaOSS/k3d-action@v2&lt;/a&gt; that can be used for creating a transient cluster.&lt;/p&gt;

&lt;p&gt;We can add this github-action as a step in our testing job as below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- uses: AbsaOSS/k3d-action@v2
  name: Create 1st Cluster
  with:
    cluster-name: My-Test-Cluster
    args: &amp;gt;
       --agents 3
       --k3s-arg "--no-deploy=traefik, metrics server@server:*"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will create a local cluster on GitHub-Runner VM and will be destroyed once the pipeline is completed.&lt;/p&gt;

&lt;p&gt;Now, as you have created the cluster, let's also add one more step for basic checks of the cluster configuration.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Configuring and Testing the Cluster Installation
  run: |
    kubectl cluster-info --context k3d-${{ env.SELF_AGENT }}
    kubectl get nodes
    kubectl get pods -n kube-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4a3od2fe8hwl3cnhsr7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4a3od2fe8hwl3cnhsr7.png" alt="cluster-config" width="800" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will do basic checks like checking nodes &amp;amp; pods in kube-system namespace. (You don't want to create a cluster locally just to check why is it not getting created, right?)&lt;/p&gt;
&lt;h2&gt;
  
  
  Application Setup
&lt;/h2&gt;

&lt;p&gt;Well, we have created our test cluster &amp;amp; also added some validation checks. Let's automate the installation of our application in the pipeline.&lt;/p&gt;

&lt;p&gt;For installing ChaosCenter, we use the k8s manifest which has all the components declared. Well, we could have added 2 simple commands for the same -&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://raw.githubusercontent.com/litmuschaos/litmus/master/litmus-portal/cluster-k8s-manifest.yml --output litmus-portal-setup.yml

kubectl apply -f litmus-portal-setup.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The above approach would have worked, but it's not flexible or scalable, right? What if there are more commands required for installation? I mean, we don't want to make our pipeline configuration very complex by adding the long list of commands, right?&lt;/p&gt;

&lt;p&gt;We can use a bash script for the same. This will help in isolating all instructions related to the installation of the application. Also, future instructions can be added to the same script.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#application-installation.sh
#!/bin/bash

function install() {

    echo -e "\n---------------Installing Litmus-Portal in Cluster Scope----------\n"
    curl https://raw.githubusercontent.com/litmuschaos/litmus/master/litmus-portal/cluster-k8s-manifest.yml --output litmus-portal-setup.yml

    kubectl apply -f litmus-portal-setup.yml
}

install

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, we can add a step in our pipeline workflow for executing this bash script.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Deploying Litmus-Portal using **k8s-manifest**
  run: |
    chmod 755 ./litmus/application-installation.sh
    ./litmus/application-installation.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, coming to the issue here, If you have worked with a cloud-native application, you know it takes time for all pods to come in the &lt;code&gt;Running&lt;/code&gt; state. So, we need to have some logic to wait for all pods to be ready before starting testing, otherwise, your tests will fail if the application is not ready.&lt;/p&gt;

&lt;p&gt;We will extend our installation script to have some validation checks for application as well as to wait for all pods to be &lt;code&gt;ready&lt;/code&gt; like we did for our k8s cluster.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#application-installation.sh
#!/bin/bash

function install() {

    echo -e "\n---------------Installing Litmus-Portal in Cluster Scope----------\n"
    curl https://raw.githubusercontent.com/litmuschaos/litmus/master/litmus-portal/cluster-k8s-manifest.yml --output litmus-portal-setup.yml

    kubectl apply -f litmus-portal-setup.yml
}

function wait_for_portal_to_be_ready(){

    echo -e "\n---------------Pods running in litmus Namespace---------------\n"
    kubectl get pods -n litmus

    echo -e "\n---------------Waiting for all pods to be ready---------------\n"
    # Waiting for pods to be ready (timeout - 360s)
    wait_for_pods litmus 360

    echo -e "\n------------- Verifying Namespace, Deployments, pods and Images for Litmus-Portal ------------------\n"
    # Namespace verification
    verify_namespace litmus

    # Deployments verification
    verify_all_components litmusportal-frontend,litmusportal-server litmus

    # Pods verification
    verify_pod litmusportal-frontend litmus
    verify_pod litmusportal-server litmus
    verify_pod mongo litmus
}

install
wait_for_portal_to_be_ready
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fku0iz5yq2xf9cutxt1vn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fku0iz5yq2xf9cutxt1vn.png" alt="pipeline-2" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above bash-script will install or application as well as will make sure that the application is ready for testing by validating the status of pods as well as the existence of different resources like pods/deployments/namespaces.&lt;/p&gt;

&lt;p&gt;If you are testing an static website/application, you can use&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And for docker-compose based applications -&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Accessing the Application
&lt;/h3&gt;

&lt;p&gt;Till now, we have automated the configuration of the Kubernetes cluster as well as our application setup. The next step is to automate the part, where we get access URL for the application &amp;amp; use it for E2E-Testing.&lt;/p&gt;

&lt;p&gt;So, if you have already worked with k8s, you must already know that we can access an application on k8s using multiple types of services or even using port-forwarding.&lt;/p&gt;

&lt;p&gt;Let's start with port-forwarding - &lt;/p&gt;

&lt;p&gt;So, for accessing our application using port-forwarding, we can use this command -&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl port-forward svc/litmusportal-frontend-service 9091:9091 -n litmus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will open a port-forwarded pipe from the port (9091) on the host machine to the port (9091, where our frontend pod is listening) of the pod deployed on a k8s cluster and allow us to access our frontend on port 9091 on localhost.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xeb59t5l13p9xkatt36.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xeb59t5l13p9xkatt36.png" alt="terminal" width="800" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can test the same by opening &lt;code&gt;http://localhost:9091&lt;/code&gt; &amp;amp; checking if we can access our frontend on the browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpgea5j3n8elj22udvxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpgea5j3n8elj22udvxd.png" alt="Browser" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, this will work fine, but there is one issue.&lt;/p&gt;

&lt;p&gt;If you run the above command, then you will no longer be able to access that terminal until and unless we stop the port-forwarding, this will hang our pipeline as this command will never complete.&lt;/p&gt;

&lt;p&gt;That's where the ampersand symbol (&amp;amp;) comes to help. If we run the same command accompanied with a &lt;code&gt;&amp;amp;&lt;/code&gt;, then it will start the port-forwarding process in the background &amp;amp; continue with other commands.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fardi867eos76uzx4cyij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fardi867eos76uzx4cyij.png" alt="Terminal-2" width="773" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, we added the same in our pipeline &amp;amp; it started working fine for us.&lt;/p&gt;
&lt;h3&gt;
  
  
  Running Tests with generated Access Endpoint -
&lt;/h3&gt;

&lt;p&gt;Finally, This part is easy with Cypress. As we are using Github-Actions, Cypress also provides a github-action, which can be used in the pipeline workflow very easily. Let's take a look at the step for the same.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Running basic tests (Login and Onboarding Tests)
  uses: cypress-io/github-action@v2
  continue-on-error: false
  with:
    spec: cypress/integration/Basic_Setup/**/*.spec.js
    working-directory: Cypress/
    config-file: cypress.prod.json
    env: true
  env:
    CYPRESS_BASE_URL: ${{ env.URL }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If we closely look at the above snippet, we can see that we are using &lt;code&gt;cypress-io/github-action@v2&lt;/code&gt; provided by Cypress &amp;amp; we are also providing some configurations.&lt;/p&gt;

&lt;p&gt;Here, &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;spec&lt;/strong&gt; - For the tests files we want to run, we can give the exact path or regex.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;working-directory&lt;/strong&gt; - Root directory where Cypress is installed or set up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;config-file&lt;/strong&gt; - configuration file we want to use for testing. This is beneficial when we have multiple environments we want to test. In our case, We provide 2 modes of installation of LitmusChaos, so we created 2 different configurations for the same.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Last environment variables, We are providing BASE_URL as env &lt;code&gt;CYPRESS_BASE_URL&lt;/code&gt;. This helps us not to hardcode the Access endpoint in our tests and take it according to the environment, so the same tests can be used for different environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdh7lt3elbmmd8rc3mwp1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdh7lt3elbmmd8rc3mwp1.png" alt="tests" width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this setup, we completed our minimal complete automated testing pipeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fep4ngdtu0r7j8qttuf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fep4ngdtu0r7j8qttuf.gif" alt="one-more-thing" width="498" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, as a bonus, as I had said in starting that we are going to use the K3d cluster, Let's also look at why we chose to do so.&lt;/p&gt;

&lt;p&gt;As we were using port-forwarding for accessing our frontend in the pipeline, there was one issue that we faced. Our tests were having little flakiness. After looking into the issue, we found the culprit. The tests were fine, but the port-forwarding pipe was getting closed in between sometimes. That was because of large chunks getting transferred through the pipe while testing through the frontend. The port-forwarding pipe is having a limit for timeout as well as the size of data/chunks getting transferred. Take a look at this &lt;a href="https://github.com/kubernetes/kubernetes/issues/74551" rel="noopener noreferrer"&gt;issue&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;This was the time, we shifted from port-forwarding &amp;amp; started looking into other approaches like accessing the same using NodePort/LoadBalancer/Ingress from the k8s cluster while testing.&lt;/p&gt;

&lt;p&gt;Now, for automating the above, we created custom functions in the bash script itself and used the same.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Function to get Access point of ChaosCenter based on Service type(mode) deployed in given namespace
function get_access_point(){
    namespace=$1
    accessType=$2

    if [[ "$accessType" == "LoadBalancer" ]];then

        kubectl patch svc litmusportal-frontend-service -p '{"spec": {"type": "LoadBalancer"}}' -n ${namespace}
        export loadBalancer=$(kubectl get services litmusportal-frontend-service -n ${namespace} -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
        wait_for_pods ${namespace} 360
        wait_for_loadbalancer litmusportal-frontend-service ${namespace}
        export loadBalancerIP=$(kubectl get services litmusportal-frontend-service -n ${namespace} -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
        export AccessURL="http://$loadBalancerIP:9091"
        wait_for_url $AccessURL
        echo "URL=$AccessURL" &amp;gt;&amp;gt; $GITHUB_ENV

    elif [[ "$accessType" == "Ingress" ]];then

        setup_ingress ${namespace}
        # Ingress IP for accessing Portal
        export AccessURL=$(kubectl get ing litmus-ingress -n ${namespace} -o=jsonpath='{.status.loadBalancer.ingress[0].ip}' | awk '{print $1}')
        echo "URL=http://$AccessURL" &amp;gt;&amp;gt; $GITHUB_ENV

    else 
        # By default NodePort will be used. 
        export NODE_NAME=$(kubectl -n ${namespace} get pod  -l "component=litmusportal-frontend" -o=jsonpath='{.items[*].spec.nodeName}')
        export NODE_IP=$(kubectl -n ${namespace} get nodes $NODE_NAME -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}')
        export NODE_PORT=$(kubectl -n ${namespace} get -o jsonpath="{.spec.ports[0].nodePort}" services litmusportal-frontend-service)
        export AccessURL="http://$NODE_IP:$NODE_PORT"
        echo "URL=$AccessURL" &amp;gt;&amp;gt; $GITHUB_ENV

    fi
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, we called this function in our installation script and took &lt;code&gt;accessType&lt;/code&gt; as env in bash script &amp;amp; passed it to this function.&lt;/p&gt;

&lt;p&gt;If you are interested in learning more about the different custom functions that we used as in the above bash script, you can take a look at this utility bash &lt;a href="https://github.com/litmuschaos/litmus-e2e/blob/master/litmus/utils.sh" rel="noopener noreferrer"&gt;script&lt;/a&gt; &amp;amp; also complete pipeline configuration can be found &lt;a href="https://github.com/litmuschaos/litmus-e2e/blob/master/.github/workflows/portal-pipeline.yml" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Feel free to check out our ongoing project - &lt;a href="https://github.com/litmuschaos/litmus/tree/master/litmus-portal" rel="noopener noreferrer"&gt;Chaos Center&lt;/a&gt; and do let us know if you have any suggestions or feedback regarding the same. You can always submit a PR if you find any required changes.&lt;/p&gt;

&lt;p&gt;Make sure to reach out to us if you have any feedback or queries. Hope you found the blog informative!&lt;/p&gt;

&lt;p&gt;If chaos engineering is something that excites you or if you want to know more about cloud-native chaos engineering, don’t forget to check out our &lt;a href="https://litmuschaos.io/" rel="noopener noreferrer"&gt;Litmus website&lt;/a&gt;, &lt;a href="https://hub.litmuschaos.io/" rel="noopener noreferrer"&gt;ChaosHub&lt;/a&gt;, and the &lt;a href="https://github.com/litmuschaos/litmus" rel="noopener noreferrer"&gt;Litmus repo&lt;/a&gt;. Do leave a star if you find it insightful. 😊&lt;/p&gt;

&lt;p&gt;I would love to invite you to our community to stay connected with us and get your Chaos Engineering doubts cleared.&lt;br&gt;
To join our slack please follow the following steps!&lt;/p&gt;

&lt;p&gt;Step 1: Join the Kubernetes slack using the following link: &lt;a href="https://slack.k8s.io/" rel="noopener noreferrer"&gt;https://slack.k8s.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 2: Join the #litmus channel on the Kubernetes slack or use this link after joining the Kubernetes slack: &lt;a href="https://slack.litmuschaos.io/" rel="noopener noreferrer"&gt;https://slack.litmuschaos.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/litmuschaos" rel="noopener noreferrer"&gt;
        litmuschaos
      &lt;/a&gt; / &lt;a href="https://github.com/litmuschaos/litmus" rel="noopener noreferrer"&gt;
        litmus
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Litmus helps  SREs and developers practice chaos engineering in a Cloud-native way. Chaos experiments are published at the ChaosHub  (https://hub.litmuschaos.io). Community notes is at https://hackmd.io/a4Zu_sH4TZGeih-xCimi3Q
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;&lt;a href="https://litmuschaos.io/" rel="nofollow noopener noreferrer"&gt;LitmusChaos&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://avatars.githubusercontent.com/u/49853472?s=200&amp;amp;v=4"&gt;&lt;img alt="LitmusChaos" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F49853472%3Fs%3D200%26v%3D4" width="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Open Source Chaos Engineering Platform&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://slack.litmuschaos.io" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/48844a2a28b222b400e3fbeb358770903bdcb4db693ac67fae37db71869352f6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f536c61636b2d4a6f696e2d707572706c65" alt="Slack Channel"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/litmuschaos/litmus/actions/workflows/push.yml/badge.svg?branch=master"&gt;&lt;img src="https://github.com/litmuschaos/litmus/actions/workflows/push.yml/badge.svg?branch=master" alt="GitHub Workflow"&gt;&lt;/a&gt;
&lt;a href="https://hub.docker.com/r/litmuschaos/chaos-operator" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2a2ae2b0d21ae55811e5da33f40b76a4aa18cd37d027ab13c5f3a4b6230ef55b/68747470733a2f2f696d672e736869656c64732e696f2f646f636b65722f70756c6c732f6c69746d75736368616f732f6368616f732d6f70657261746f722e737667" alt="Docker Pulls"&gt;&lt;/a&gt;
&lt;a href="https://github.com/litmuschaos/litmus/stargazers" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e87b930f5b0b40039776ad0d255d62735311c7d7228bb7615d7408161915c0b2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f6c69746d75736368616f732f6c69746d75733f7374796c653d736f6369616c" alt="GitHub stars"&gt;&lt;/a&gt;
&lt;a href="https://github.com/litmuschaos/litmus/issues" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2f66885a8b6af96fe90f93b8aa9085f6065fb43e9c0a4a602219a01e7a142548/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f6c69746d75736368616f732f6c69746d7573" alt="GitHub issues"&gt;&lt;/a&gt;
&lt;a href="https://twitter.com/LitmusChaos" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/6425eb889e05cdadcf0db2a952db7e9dda44ca3df091c5ca9feea8515a2ac44f/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f6c69746d75736368616f733f7374796c653d736f6369616c" alt="Twitter Follow"&gt;&lt;/a&gt;
&lt;a href="https://www.bestpractices.dev/projects/3202" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a8d5ed826be562a3339ce503c6ff3f4ab2cc63227b18ba5f65648fdb3ca04eec/68747470733a2f2f7777772e626573747072616374696365732e6465762f70726f6a656374732f333230322f6261646765" alt="OpenSSF Best Practices"&gt;&lt;/a&gt;
&lt;a href="https://app.fossa.io/projects/git%2Bgithub.com%2Flitmuschaos%2Flitmus?ref=badge_shield" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/848851b5714a120bc84e06ebdb121f455a4a472a782a90d6f4efb681fa9be392/68747470733a2f2f6170702e666f7373612e696f2f6170692f70726f6a656374732f6769742532426769746875622e636f6d2532466c69746d75736368616f732532466c69746d75732e7376673f747970653d736869656c64" alt="FOSSA Status"&gt;&lt;/a&gt;
&lt;a href="https://www.youtube.com/channel/UCa57PMqmz_j0wnteRa9nCaw" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8420bd8ea7dfc02f130445cdcf5f3adec631ea57f9682afc56af5940cc5ca044/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f596f75547562652d5375627363726962652d726564" alt="YouTube Channel"&gt;&lt;/a&gt;
&lt;a href="https://gurubase.io/g/litmuschaos" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/d14b84f34d827a00ea3da041c025456fa77e2143b06396c17636f4531500eb23/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f47757275626173652d41736b2532304c69746d75734368616f73253230477572752d303036424646" alt="Gurubase"&gt;&lt;/a&gt;
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;&lt;em&gt;Read this in &lt;a href="https://github.com/litmuschaos/litmus/translations/TRANSLATIONS.md" rel="noopener noreferrer"&gt;other languages&lt;/a&gt;.&lt;/em&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/litmuschaos/litmus/translations/README-ko.md" rel="noopener noreferrer"&gt;🇰🇷&lt;/a&gt; &lt;a href="https://github.com/litmuschaos/litmus/translations/README-chn.md" rel="noopener noreferrer"&gt;🇨🇳&lt;/a&gt; &lt;a href="https://github.com/litmuschaos/litmus/translations/README-pt-br.md" rel="noopener noreferrer"&gt;🇧🇷&lt;/a&gt; &lt;a href="https://github.com/litmuschaos/litmus/translations/README-hi.md" rel="noopener noreferrer"&gt;🇮🇳&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Overview&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;LitmusChaos is an open source Chaos Engineering platform that enables teams to identify weaknesses &amp;amp; potential outages in infrastructures by
inducing chaos tests in a controlled way. Developers &amp;amp; SREs can practice Chaos Engineering with LitmusChaos as it is easy to use, based on modern
Chaos Engineering principles &amp;amp; community collaborated. It is 100% open source &amp;amp; a CNCF project.&lt;/p&gt;
&lt;p&gt;LitmusChaos takes a cloud-native approach to create, manage and monitor chaos. The platform itself runs as a set of microservices and uses Kubernetes
custom resources (CRs) to define the chaos intent, as well as the steady state hypothesis.&lt;/p&gt;
&lt;p&gt;At a high-level, Litmus comprises of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chaos Control Plane&lt;/strong&gt;: A centralized chaos management tool called chaos-center, which helps construct, schedule and visualize Litmus chaos workflows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chaos Execution Plane Services&lt;/strong&gt;: Made up of a…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/litmuschaos/litmus" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>kubernetes</category>
      <category>bash</category>
      <category>productivity</category>
      <category>devops</category>
    </item>
    <item>
      <title>Frontend Optimization at LitmusChaos</title>
      <dc:creator>Vedant Shrotria</dc:creator>
      <pubDate>Tue, 01 Mar 2022 12:00:00 +0000</pubDate>
      <link>https://dev.to/litmus-chaos/frontend-optimization-at-litmuschaos-1p14</link>
      <guid>https://dev.to/litmus-chaos/frontend-optimization-at-litmuschaos-1p14</guid>
      <description>&lt;p&gt;&lt;em&gt;Hi Folks!!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Hmm, So you have already developed an application &amp;amp; you are looking at how to optimize it?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In this article, We will be taking you through the journey that we followed while working on frontend optimization at LitmusChaos.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Firstly, Why did we have to work on optimization for our frontend?
&lt;/h2&gt;

&lt;p&gt;So, as we all know, first impressions make sure how further things are going to move forward, right? The same thing goes with your Software. And as we are talking about Software, When your client is going to open that great application you made, What if that application takes a very long time to load &amp;amp; they are waiting just to log in. And that even when that application is not even at its peak level or I would say it is not having a huge load on itself.&lt;/p&gt;

&lt;p&gt;Well, the same thing happened to us. We have been working on ChaosCenter for quite a long time now and it has grown to a very large extent. Last year, We found that our application was taking around 50 seconds just to load a login page. This motivated us to look into it deeply.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2drewlls7suwwt3l8byd.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2drewlls7suwwt3l8byd.gif" alt="Sherlock-Holmes-Start" width="426" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, as a developer you always start with Developer-tools, right? We also did the same &amp;amp; started looking at chunks getting transferred while loading a single page. We found that it was transferring around ~5MBs when a user was just trying to load the login page for logging in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbu2z362wvffgn4ee1ylu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbu2z362wvffgn4ee1ylu.png" alt="Network requests" width="800" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, that is a problem, right? Your application shouldn't be taking that much time to load or even that much of a big chunk shouldn't be getting transferred just for a single page.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, Are you ready for this journey?
&lt;/h2&gt;

&lt;p&gt;Well, with the benchmarking numbers we had, we started digging into the working/bundling process of React JS &amp;amp; different ways of optimizing that. And Oh!, by the way, I forgot to tell you, Our application is built using React. So, many things are already taken care of.&lt;/p&gt;

&lt;p&gt;While looking into the bundling process of Webpack, we got to know different styles of importing components (Static/Dynamic). Well, if your application is small, it doesn't matter which style you pick but an application like ours does matter.&lt;/p&gt;

&lt;p&gt;This leads us to the concept of Lazy-loading &amp;amp; code-splitting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy-Loading &amp;amp; Code-splitting
&lt;/h2&gt;

&lt;p&gt;Fortunately, we had written our codebase in such a way that all components are well isolated &amp;amp; implemented. The only problem there was that we were using static imports everywhere, due to which all the components were getting loaded, whichever was imported in a file. And when we started looking into our codebase, we found that we had a central file, which has the routing logic &amp;amp; all the pages/views were getting imported there. &lt;/p&gt;

&lt;p&gt;Let's look at the below example snippet from our Router file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import CreateWorkflow from '../../pages/CreateWorkflow';
import LoginPage from '../../pages/LoginPage';
import GetStarted from '../../pages/GetStartedPage';
import WorkflowDetails from '../../pages/WorkflowDetails'

# Router component
&amp;lt;Router history={history}&amp;gt;
  {/* &amp;lt;Routes /&amp;gt; */}
  &amp;lt;Routes /&amp;gt;
&amp;lt;/Router&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So If you see here, the router was working as intended, whenever a user started the app, it was routed to the sign-in page. But if we check the background, &lt;strong&gt;it was loading all the pages/views &amp;amp; then redirecting to the sign-in page&lt;/strong&gt;.&lt;br&gt;
Here, what we wanted was to &lt;strong&gt;just load the sign-in page &amp;amp; route to it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So we started with Router-based code-splitting. We changed all static imports from static to dynamic imports using built-in lazy-loading from Webpack &amp;amp; React.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const CreateWorkflow = lazy(() =&amp;gt; import('../../pages/CreateWorkflow'));
const LoginPage = lazy(() =&amp;gt; import('../../pages/LoginPage'));
const GetStarted = lazy(() =&amp;gt; import('../../pages/GetStartedPage'));
const WorkflowDetails = lazy(() =&amp;gt; import('../../pages/WorkflowDetails'));

# Router component
&amp;lt;Suspense fallback={&amp;lt;Loader /&amp;gt;} &amp;gt;
  &amp;lt;Router history={history}&amp;gt;
     {/* &amp;lt;Routes /&amp;gt; */}
     &amp;lt;Routes /&amp;gt;
  &amp;lt;/Router&amp;gt;
&amp;lt;/Suspense&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With the above changes, On trying to login to the application, Webpack will fetch the Router component chunk &amp;amp; then only the Login-page chunk as only that is required.&lt;/p&gt;

&lt;p&gt;Now, at this time, we tried to build our frontend. And believe me, we knew that we had something because we had divided our build chunks from having size 3MBs to 1.5-2MBs.&lt;/p&gt;

&lt;p&gt;Moving ahead, We also followed the same approach at the components level &amp;amp; changed all component imports in our pages by analyzing user stories to dynamic ones. &lt;/p&gt;

&lt;p&gt;Well, you might be having a question why would a component imported on a page be imported as dynamic?&lt;/p&gt;

&lt;p&gt;Let's take an example, you can have a page, where on clicking on a button, you show a modal or in our case a complete Code Editor. Well, a code editor is a big component and users might not even click on that button. So, We changed the imports everywhere to dynamic ones. I think with this you must have got the point here.&lt;/p&gt;

&lt;p&gt;The previous exercise had a great impact on our number of chunks (~98 chunks) &amp;amp; their sizes, (Obviously on load time as well) as you can see in the below screenshot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7bgj0qcpwueovggsk6eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7bgj0qcpwueovggsk6eg.png" alt="Build" width="643" height="561"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Sources Tab, Your good friend?
&lt;/h2&gt;

&lt;p&gt;We started digging more into different functionalities of Chrome, lighthouse &amp;amp; other tools. We found that Chrome provides a sources tab in Developer tools. Whenever we open an application or website, Source Tab provides us with all resources imported to that instance for having that software/website/app working as ideal. We saw that when we were just trying to open the Login page, It was importing all components from our component library, even though no other page/screen was getting loaded. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqn26bma3hpmoz9vk38u2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqn26bma3hpmoz9vk38u2.jpg" alt="Sources Tab" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay okay, I didn't tell you, we also have our Component library &lt;a href="https://github.com/litmuschaos/litmus-ui" rel="noopener noreferrer"&gt;(litmus-ui)&lt;/a&gt; built upon Rollup. This is a very well maintained &amp;amp; optimized component library that we use for our different products.&lt;/p&gt;

&lt;p&gt;Well, interestingly, if you see in the above image, Our Login page was only using text-boxes &amp;amp; buttons. But, other components including analytics-related graphical components, icons &amp;amp; even lab components were getting loaded in the browser, which was not getting used or imported into the login page.&lt;/p&gt;

&lt;p&gt;So, we started looking deeply in our Library, tried making some changes here &amp;amp; there, and tested with a small React App (Well, you don't want to wait for a build just for a single change, right). In all cases, it was importing all components from our library.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0uvywcaar45ejmbzfoi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0uvywcaar45ejmbzfoi.gif" alt="Starting the Investigation" width="498" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After looking into other component libraries, we found one pattern and that was for every component, they were having &lt;strong&gt;default exports&lt;/strong&gt; along with named exports. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7l8yhwptkzc1oveonub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7l8yhwptkzc1oveonub.png" alt="Enhancing Imports" width="652" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This ensured that no redundant code/components were loaded whenever a single component was imported from the library and also &lt;strong&gt;helped us in allowing path-based imports from our library&lt;/strong&gt; as shown below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Previously only this was possible
import {ButtonFilled} from "litmus-ui";

# Now, all below given imports are possible
import { ButtonFilled } from "litmus-ui";
import { ButtonFilled } from "litmus-ui/core";
import { ButtonFilled } from "litmus-ui/core/Button";
import { ButtonFilled } from "litmus-ui/core/Button/ButtonFilled";
import ButtonFilled from "litmus-ui/core/Button/ButtonFilled"; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  What about Tree-shaking at the Components-library level?
&lt;/h2&gt;

&lt;p&gt;Well, with the above analysis we were sure that tree-shaking in our library wasn't working as expected. We started looking into tree-shaking more at the library level.&lt;/p&gt;

&lt;p&gt;We stepped inside &lt;strong&gt;node_modules&lt;/strong&gt;, after many hits &amp;amp; trials and comparing other libraries, we found that our library wasn't even supporting tree-shaking. Let's see the reason in the below picture as well as &lt;code&gt;rollup.config.js&lt;/code&gt; that we had earlier -&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  output: [
    {
      dir: "dist",
      format: "cjs",
      sourcemap: true,
    },
  ],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foq449nu839ix9jaixw2m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foq449nu839ix9jaixw2m.png" alt="Node_Modules" width="291" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above picture, if you see, our library was only bundled to &lt;code&gt;cjs&lt;/code&gt; (commonJS) format, which doesn't support tree-shaking.&lt;/p&gt;

&lt;p&gt;Then we started looking into what we can do to achieve it. Well, this was the time when we found that &lt;code&gt;esm&lt;/code&gt; (ES Modules) format is the one that supports this. So we changed our configuration file of the library to create the bundle in &lt;code&gt;esm&lt;/code&gt; format.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  output: [
    {
      dir: "dist",
      format: "cjs",
      sourcemap: true,
    },
    {
      dir: "dist",
      format: "esm",
      sourcemap: true,
    },
  ],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Well, in the above configuration, we had made one mistake i.e. we had given the same destination directory as &lt;code&gt;dist&lt;/code&gt; in both outputs, which in return was overriding each other and we were only getting &lt;code&gt;cjs&lt;/code&gt; format.&lt;/p&gt;

&lt;p&gt;So we changed the output dir for &lt;code&gt;esm&lt;/code&gt; to &lt;code&gt;dist/esm&lt;/code&gt;, with this in place, we had our &lt;code&gt;esm&lt;/code&gt; bundle generated.&lt;/p&gt;

&lt;p&gt;Now, our rollup.config.js was looking like below -&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  output: [
    {
      dir: "dist",
      format: "cjs",
      sourcemap: true,
    },
    {
      dir: "dist/esm",
      format: "esm",
      sourcemap: true,
    },
  ],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F008elzemg7ivn7my8fye.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F008elzemg7ivn7my8fye.png" alt="Node_Modules-1" width="295" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Still, the same result, React wasn't using the &lt;code&gt;esm&lt;/code&gt; module in our application. And we were also having one question in our mind, well we have bundled our library in 2 formats but how are we going to tell React to use &lt;code&gt;esm&lt;/code&gt; format?&lt;/p&gt;

&lt;p&gt;After a little research, we found that we have to provide a path for &lt;code&gt;esm&lt;/code&gt; bundle in the &lt;code&gt;module&lt;/code&gt; field in package.json of our component library. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1du0fw3oxda41iz8lyys.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1du0fw3oxda41iz8lyys.gif" alt="Found It" width="498" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, we added both paths for &lt;code&gt;cjs&lt;/code&gt; &amp;amp; &lt;code&gt;esm&lt;/code&gt; in package.json in the fields &lt;code&gt;main&lt;/code&gt; &amp;amp; &lt;code&gt;module&lt;/code&gt; respectively. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ycppptu3mvx8s6yrdo5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ycppptu3mvx8s6yrdo5.png" alt="Tress-shakable" width="306" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above configuration made our library be used easily by both traditional bundlers as well as modern bundlers like webpack.&lt;/p&gt;

&lt;p&gt;NOTE: Traditional bundlers who don't understand the &lt;code&gt;esm&lt;/code&gt; type can make use of &lt;code&gt;cjs&lt;/code&gt; with this configuration.&lt;/p&gt;

&lt;p&gt;Well, while we were looking into this, we got our eyes on the build output of the library, we saw that it was creating only one chunk because we were giving only one entry-point in config. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mk4dgy2dlggr0qni7hb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mk4dgy2dlggr0qni7hb.png" alt="Terminal-1" width="800" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We tried with an array of entry points (One root &amp;amp; one for only one of the components). And well, guess what we had achieved what we wanted. We tried importing the same component, and only that component was loaded.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input: ["./src/index.ts","./src/core/Button/ButtonFilled/index.ts" ],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbon32tme23i7mt1hbbz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbon32tme23i7mt1hbbz.png" alt="Terminal-2" width="714" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, now we had all the things with us and we knew what we had to do. Firstly we thought let's just make a rule for every developer to add an entry-point in an array whenever he/she adds a new component. But then we thought this can have issues as we can forget to do so every time, After all, We all are Humans :-).&lt;/p&gt;

&lt;p&gt;So, we made a script in JS which would go through all components and extract their relative paths &amp;amp; provide them as an array to the entry point in the config input.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# scripts/inputs.js
const fs = require("fs");
const path = require("path");

const getAllEntryPoints = function (dirPath, arrayOfFiles) {
  let files = fs.readdirSync(dirPath);
  arrayOfFiles = arrayOfFiles || [];

  files.forEach(function (file) {
    if (fs.statSync(dirPath + "/" + file).isDirectory()) {
      arrayOfFiles = getAllEntryPoints(dirPath + "/" + file, arrayOfFiles);
    } else {
      if (file === "index.ts") {
        arrayOfFiles.push(path.join(dirPath, "/", file));
      }
    }
  });

  return arrayOfFiles;
};

export default getAllEntryPoints;


# In rollup.config.js

import getAllEntryPoints from "./scripts/inputs";
const input = getAllEntryPoints("./src");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And with this, we were able to make our library Tree-shakable &amp;amp; still developer-friendly at the same time. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb644rwkh5ywplu5kpmb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb644rwkh5ywplu5kpmb.png" alt="Terminal-2" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, After this whole exercise &amp;amp; brain-storming, what we saw - &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcith9m33ze5xjkj51e5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcith9m33ze5xjkj51e5.png" alt="Opti-1" width="800" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And with help of different compression techniques using brotli &amp;amp; gzip, we were able to achieve the below results - &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhir45lw0wbwur999og0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhir45lw0wbwur999og0.png" alt="Compression" width="800" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was a great exercise for us as we got to know more about the bundling process, optimization techniques as well as the working of component libraries.&lt;/p&gt;

&lt;p&gt;Well, This is it for now, Thanks for staying with me till here, Will be sharing more..as this is going to be continued, let's see what can be done to go below 2 MBs without compression.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F10z76nh4iq88n9170w11.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F10z76nh4iq88n9170w11.gif" alt="Making Life Better" width="498" height="280"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Feel free to check out our ongoing project - &lt;a href="https://github.com/litmuschaos/litmus/tree/master/litmus-portal" rel="noopener noreferrer"&gt;Chaos Center&lt;/a&gt; and do let us know if you have any suggestions or feedback regarding the same. You can always submit a PR if you find any required changes.&lt;/p&gt;

&lt;p&gt;Make sure to reach out to us if you have any feedback or queries. Hope you found the blog informative!&lt;/p&gt;

&lt;p&gt;If chaos engineering is something that excites you or if you want to know more about cloud-native chaos engineering, don’t forget to check out our &lt;a href="https://litmuschaos.io/" rel="noopener noreferrer"&gt;Litmus website&lt;/a&gt;, &lt;a href="https://hub.litmuschaos.io/" rel="noopener noreferrer"&gt;ChaosHub&lt;/a&gt;, and the &lt;a href="https://github.com/litmuschaos/litmus" rel="noopener noreferrer"&gt;Litmus repo&lt;/a&gt;. Do leave a star if you find it insightful. 😊&lt;/p&gt;

&lt;p&gt;I would love to invite you to our community to stay connected with us and get your Chaos Engineering doubts cleared.&lt;br&gt;
To join our slack please follow the following steps!&lt;/p&gt;

&lt;p&gt;Step 1: Join the Kubernetes slack using the following link: &lt;a href="https://slack.k8s.io/" rel="noopener noreferrer"&gt;https://slack.k8s.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 2: Join the #litmus channel on the Kubernetes slack or use this link after joining the Kubernetes slack: &lt;a href="https://slack.litmuschaos.io/" rel="noopener noreferrer"&gt;https://slack.litmuschaos.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/litmuschaos" rel="noopener noreferrer"&gt;
        litmuschaos
      &lt;/a&gt; / &lt;a href="https://github.com/litmuschaos/litmus" rel="noopener noreferrer"&gt;
        litmus
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Litmus helps  SREs and developers practice chaos engineering in a Cloud-native way. Chaos experiments are published at the ChaosHub  (https://hub.litmuschaos.io). Community notes is at https://hackmd.io/a4Zu_sH4TZGeih-xCimi3Q
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;&lt;a href="https://litmuschaos.io/" rel="nofollow noopener noreferrer"&gt;LitmusChaos&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://avatars.githubusercontent.com/u/49853472?s=200&amp;amp;v=4"&gt;&lt;img alt="LitmusChaos" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F49853472%3Fs%3D200%26v%3D4" width="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Open Source Chaos Engineering Platform&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://slack.litmuschaos.io" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/48844a2a28b222b400e3fbeb358770903bdcb4db693ac67fae37db71869352f6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f536c61636b2d4a6f696e2d707572706c65" alt="Slack Channel"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/litmuschaos/litmus/actions/workflows/push.yml/badge.svg?branch=master"&gt;&lt;img src="https://github.com/litmuschaos/litmus/actions/workflows/push.yml/badge.svg?branch=master" alt="GitHub Workflow"&gt;&lt;/a&gt;
&lt;a href="https://hub.docker.com/r/litmuschaos/chaos-operator" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2a2ae2b0d21ae55811e5da33f40b76a4aa18cd37d027ab13c5f3a4b6230ef55b/68747470733a2f2f696d672e736869656c64732e696f2f646f636b65722f70756c6c732f6c69746d75736368616f732f6368616f732d6f70657261746f722e737667" alt="Docker Pulls"&gt;&lt;/a&gt;
&lt;a href="https://github.com/litmuschaos/litmus/stargazers" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e87b930f5b0b40039776ad0d255d62735311c7d7228bb7615d7408161915c0b2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f6c69746d75736368616f732f6c69746d75733f7374796c653d736f6369616c" alt="GitHub stars"&gt;&lt;/a&gt;
&lt;a href="https://github.com/litmuschaos/litmus/issues" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2f66885a8b6af96fe90f93b8aa9085f6065fb43e9c0a4a602219a01e7a142548/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f6c69746d75736368616f732f6c69746d7573" alt="GitHub issues"&gt;&lt;/a&gt;
&lt;a href="https://twitter.com/LitmusChaos" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/6425eb889e05cdadcf0db2a952db7e9dda44ca3df091c5ca9feea8515a2ac44f/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f6c69746d75736368616f733f7374796c653d736f6369616c" alt="Twitter Follow"&gt;&lt;/a&gt;
&lt;a href="https://www.bestpractices.dev/projects/3202" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a8d5ed826be562a3339ce503c6ff3f4ab2cc63227b18ba5f65648fdb3ca04eec/68747470733a2f2f7777772e626573747072616374696365732e6465762f70726f6a656374732f333230322f6261646765" alt="OpenSSF Best Practices"&gt;&lt;/a&gt;
&lt;a href="https://app.fossa.io/projects/git%2Bgithub.com%2Flitmuschaos%2Flitmus?ref=badge_shield" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/848851b5714a120bc84e06ebdb121f455a4a472a782a90d6f4efb681fa9be392/68747470733a2f2f6170702e666f7373612e696f2f6170692f70726f6a656374732f6769742532426769746875622e636f6d2532466c69746d75736368616f732532466c69746d75732e7376673f747970653d736869656c64" alt="FOSSA Status"&gt;&lt;/a&gt;
&lt;a href="https://www.youtube.com/channel/UCa57PMqmz_j0wnteRa9nCaw" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8420bd8ea7dfc02f130445cdcf5f3adec631ea57f9682afc56af5940cc5ca044/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f596f75547562652d5375627363726962652d726564" alt="YouTube Channel"&gt;&lt;/a&gt;
&lt;a href="https://gurubase.io/g/litmuschaos" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/d14b84f34d827a00ea3da041c025456fa77e2143b06396c17636f4531500eb23/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f47757275626173652d41736b2532304c69746d75734368616f73253230477572752d303036424646" alt="Gurubase"&gt;&lt;/a&gt;
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;&lt;em&gt;Read this in &lt;a href="https://github.com/litmuschaos/litmus/translations/TRANSLATIONS.md" rel="noopener noreferrer"&gt;other languages&lt;/a&gt;.&lt;/em&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/litmuschaos/litmus/translations/README-ko.md" rel="noopener noreferrer"&gt;🇰🇷&lt;/a&gt; &lt;a href="https://github.com/litmuschaos/litmus/translations/README-chn.md" rel="noopener noreferrer"&gt;🇨🇳&lt;/a&gt; &lt;a href="https://github.com/litmuschaos/litmus/translations/README-pt-br.md" rel="noopener noreferrer"&gt;🇧🇷&lt;/a&gt; &lt;a href="https://github.com/litmuschaos/litmus/translations/README-hi.md" rel="noopener noreferrer"&gt;🇮🇳&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Overview&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;LitmusChaos is an open source Chaos Engineering platform that enables teams to identify weaknesses &amp;amp; potential outages in infrastructures by
inducing chaos tests in a controlled way. Developers &amp;amp; SREs can practice Chaos Engineering with LitmusChaos as it is easy to use, based on modern
Chaos Engineering principles &amp;amp; community collaborated. It is 100% open source &amp;amp; a CNCF project.&lt;/p&gt;
&lt;p&gt;LitmusChaos takes a cloud-native approach to create, manage and monitor chaos. The platform itself runs as a set of microservices and uses Kubernetes
custom resources (CRs) to define the chaos intent, as well as the steady state hypothesis.&lt;/p&gt;
&lt;p&gt;At a high-level, Litmus comprises of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chaos Control Plane&lt;/strong&gt;: A centralized chaos management tool called chaos-center, which helps construct, schedule and visualize Litmus chaos workflows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chaos Execution Plane Services&lt;/strong&gt;: Made up of a…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/litmuschaos/litmus" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>react</category>
      <category>litmuschaos</category>
      <category>optimization</category>
      <category>javascript</category>
    </item>
    <item>
      <title>End-To-End Testing Using Cypress</title>
      <dc:creator>Vedant Shrotria</dc:creator>
      <pubDate>Thu, 21 Jan 2021 06:29:44 +0000</pubDate>
      <link>https://dev.to/litmus-chaos/cypress-end-to-end-testing-and-experience-cn4</link>
      <guid>https://dev.to/litmus-chaos/cypress-end-to-end-testing-and-experience-cn4</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Hello Everyone&lt;/strong&gt;&lt;/em&gt;, I hope you all are rocking in your digital world. So, Here is my first blog, I will be sharing my experience and what i learned while working on end-to-end testing for Litmus-Portal. we will be going through how to get started with End-to-End testing with Cypress in any of your project and how litmus-Portal is using Cypress for testing different scenarios.Stay tuned till the end, you will get to know many awesome things.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Litmus-Portal&lt;/strong&gt; provides console and UI experience for managing, monitoring, and events around chaos workflows. Chaos workflows consist of a sequence of experiments run together to achieve the objective of introducing some kind of fault into an application or the Kubernetes platform.Using Litmus-Portal, you can make your projects or products more resilient.&lt;/p&gt;

&lt;p&gt;For doing all this and providing resiliency to your product, Litmus-Portal has to be resilient itself.That's where Cypress comes which helps us to test Litmus-Portal in different scenarios and makes it more resilient.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Cypress&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Cypress is a modern frontend End-to-End testing tool using which we can write our tests in javascript as well as Typescript. It simplifies how we write our tests, makes our tests less flaky, and helps us in reducing maintenance cost of our project. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Cypress?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Well, we could have used some other framework for our purpose but, we wanted the one, which is easy to setup and reliable.There are many advantages of using Cypress - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to setup, documentation is more than sufficient.&lt;/li&gt;
&lt;li&gt;It helps us in adapting best practices for testing with it's documentation.&lt;/li&gt;
&lt;li&gt;As Cypress shows all logs side by side to AUT (Application Under Test), it is very easy to debug our projects. &lt;/li&gt;
&lt;li&gt;A plugins catalog provided by Cypress and it's community, which is very helpful to test different scenarios.&lt;/li&gt;
&lt;li&gt;It is very easy to adapt, as it build on top of Mocha, Chai, chai-jQuery and many other libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Installing Cypress
&lt;/h4&gt;

&lt;p&gt;Cypress is an NPM package. We can install Cypress as a development dependency like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install cypress --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We can use Cypress in two modes -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Browser mode&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For using Cypress in Browser Mode, we can make use of this command -&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx cypress open
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will open a browser for you, showing different default-test scripts. We can click on different scripts to execute them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Headless mode&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For using Cypress in Headless Mode, we can make use of this command -&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx cypress run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will open a terminal for you, and start to execute the tests present in the Test scripts path (By default, Integration directory).&lt;/p&gt;

&lt;p&gt;After executing this command,you will observe that some predefined directories and files have been added in your project -&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-cypress
  |_fixtures
  |_integration
  |_plugins
  |_support
-cypress.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, cypress is the directory that contains everything required for testing using Cypress.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;fixtures/&lt;/strong&gt; - This directory contains all the static data (data you want to use for setting your Databases between tests or you want to input on your different screens) to be used while testing in form of JSON files.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;An example of User.json (fixture file for users) is given below -&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "projectname":"litmus",
    "AdminName":"John",
    "AdminPassword":"admin1234",
    "AdminEmail":"admin@gmail.com",
    "NewName":"John",
    "NewPassword":"John123",
    "NewEmail":"John@gmail.com"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;integration/&lt;/strong&gt; - This directory contains all the test scripts. We can configure a different location for storing our test scripts in cypress.json.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;plugins/index.js&lt;/strong&gt; - This file can contain configuration for all plugins installed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;support/commands.js&lt;/strong&gt; - It will contain all the custom functions that we might need while writing our test so that we don't repeat ourselves.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;support/index.js&lt;/strong&gt; - This file contains any configurations for test cases. for e.g. by default cookies are not preserved between tests. They can be preserved add following code in this file -&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// For preserving cookies between tests.
Cypress.Cookies.defaults({
    preserve: 'token'
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;cypress.json&lt;/strong&gt; - This is a configuration file for Cypress.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An example of cypress.json is given below -&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "baseUrl": "http://localhost:3001",
  "experimentalFetchPolyfill": true,
  "viewportWidth": 1800,
  "viewportHeight": 1200,
  "defaultCommandTimeout": 10000,
  "chromeWebSecurity": false,
  "video": false,
  "experimentalNetworkStubbing":true,
  "env": {
    "authURL" : "http://localhost:3000",

  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You will get to know more about them, as we proceed with testing different scenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's have something in our pocket before moving on further -&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DOM Selector&lt;/strong&gt; - It is a selector that is used for selecting different objects in DOM for testing or automation. A Selector can be any CSS property, Ids, and Classes. But let me tell you when you make a product your CSS properties, ids, and classes keep changing, which might break our tests.&lt;/p&gt;

&lt;p&gt;The best practice is to use a &lt;strong&gt;unique identifier&lt;/strong&gt; which is not much subjected to change also which is unique on a particular page for identifying an element. While using Cypress, we have the support to use &lt;code&gt;data-*&lt;/code&gt; attributes with our elements.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As a best-practice. we enforce everyone working on Litmus-Portal to use &lt;code&gt;data-cy=&amp;lt;selector&amp;gt;&lt;/code&gt; selector to every different component, so that it can targeted easily by Cypress while testing. This practice is also preferred by &lt;a href="https://docs.cypress.io/guides/references/best-practices.html#Selecting-Elements" rel="noopener noreferrer"&gt;Cypress test runner&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In Cypress, We can query an element on DOM using the command &lt;code&gt;cy.get(&amp;lt;Your_Selector&amp;gt;)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In Cypress, data-* are given high priority while querying, so it is a bit fast as well.&lt;/p&gt;

&lt;p&gt;for example, If there is button like this,&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button class="btn1"&amp;gt;Save&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We can inject a unique identifier like this&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button class="btn1" data-cy="save"&amp;gt;Save&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, we can access this button like this&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.get('[data-cy=save]');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Okay, now I think we are good with testing and Cypress, we will go deep while working with live scripts, but let's get our hands dirty a bit.&lt;/p&gt;

&lt;p&gt;Firstly, for testing an App, We need an endpoint of our WebApp.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Let's say the endpoint of our web app is &lt;strong&gt;&lt;a href="https://localhost:3001" rel="noopener noreferrer"&gt;https://localhost:3001&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Cypress, We can visit this link by using the function &lt;code&gt;visit()&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.visit("https://localhost:3001");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;But being a lazy person, we don't want to write this bigger link again and again in every test or even in different test scripts.&lt;/p&gt;

&lt;p&gt;You will be happy to know, we can also set the endpoint in cypress.json for universal use in test scripts.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In cypress.json,&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "baseUrl":"https://localhost:3001"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, anywhere in the test script, we want to visit the link, we can just do&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.visit("/");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Well, this setup will work well in local setup. But when we are working on different CI's, we won't be able to use it because every time we setup the full stack web app in CI, A dynamic Link will be getting generated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As Litmus-Portal is a cloud native web application, we have to deploy it on kubernetes while testing on different CI's. Everytime we generate a new dynamic link using loadbalancer for accessing the frontend.So, for this we needed a better approach as we can't provide access link before deploying Litmus-Portal.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But Hurray, I have something for you, We can provide the link as an environment variable to cypress while starting testing using command -&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CYPRESS_BASE_URL=$link npx cypress run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So, Cypress will use this URL as BaseURL while executing our test scripts.&lt;/p&gt;

&lt;p&gt;Now, as we know how to query an element and how to open our web app to be tested, the Next thing is how we write tests for our app.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We will be using Litmus-portal as our web app for Testing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Starting with login Page for Litmus-Portal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8054hi2h1j5m2l6pdwz0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8054hi2h1j5m2l6pdwz0.png" alt="Login Page for Litmus-Portal" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While writing tests for the Login Page, we have to consider all scenarios including positive and negative tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Positive scenario can be like this -&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visit the login page.&lt;/li&gt;
&lt;li&gt;Find the input for the name and type our correct name in it.&lt;/li&gt;
&lt;li&gt;Find the input for the password and type our correct password in it.&lt;/li&gt;
&lt;li&gt;Click on the login button.&lt;/li&gt;
&lt;li&gt;Check if we are landing on welcome modal after clicking on the login button.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;A Negative scenario can be like this -&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visit the login page.&lt;/li&gt;
&lt;li&gt;Find the input for the name and type a wrong name in it.&lt;/li&gt;
&lt;li&gt;Find the input for the password and type a wrong password in it.&lt;/li&gt;
&lt;li&gt;Click on the login button.&lt;/li&gt;
&lt;li&gt;Check if we are prompted with the error "Wrong Credentials".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let me give you a small script for login page testing,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This was what I wrote on my first try. So don't laugh.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Checking functionality of Login Page",()=&amp;gt;{

    it("Testing the only single input sign in [ Should not be possible ]",()=&amp;gt;{
        cy.visit("/");
        cy.get('[data-cy=inputName] input').type(" ");
        cy.get('[data-cy=inputPassword] input').type("John123");
        cy.get('[data-cy=loginButton]').click();
        cy.contains("Wrong Credentials").should('be.visible');
    })

    it("Testing with wrong details [ Should not be possible ]",()=&amp;gt;{
        cy.visit("/");
        cy.get('[data-cy=inputName] input').type("Johnce");
        cy.get('[data-cy=inputPassword] input').type("John123");
        cy.get('[data-cy=loginButton]').click();
        cy.url().should('include','/login');
        cy.contains("Wrong Credentials").should('be.visible');
    })

    it("Testing with Correct details [ Must redirect to Welcome modal ]",()=&amp;gt;{
        cy.visit("/");
        cy.get('[data-cy=inputName] input').type("John");
        cy.get('[data-cy=inputPassword] input').type("John123");
        cy.get('[data-cy=loginButton]').click(); //Correct Details
        cy.contains("Welcome to Portal");
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;If you have worked with Mocha before, then you must be knowing that it's BDD interface provide describe(), it(), beforeEach(), afterEach() and many other functions. If you don't, don't worry we will discuss all of them as we use them.&lt;/p&gt;

&lt;p&gt;Here, describe() is mainly used for collecting all tests under a single umbrella (Test-suite) which are related to each other or similar in objective.&lt;/p&gt;

&lt;p&gt;it() is the function which signifies one test or one scenario.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also, you must be seeing some new interactive functions as well.&lt;br&gt;
Let me explain what we are doing here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;cy.visit("/");&lt;/code&gt; visits the login page.&lt;br&gt;
&lt;code&gt;cy.get("[data-cy=inputName]")&lt;/code&gt; finds the input field for name and &lt;code&gt;type(&amp;lt;data_to_be_typed&amp;gt;)&lt;/code&gt; is used to type in the selected input field.&lt;br&gt;
&lt;code&gt;cy.contains(&amp;lt;text&amp;gt;)&lt;/code&gt; is used to search &lt;em&gt;text&lt;/em&gt; on page.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You must be seeing that we are visiting the login page again and again and also writing the same functions many times.&lt;/p&gt;

&lt;p&gt;Let's refactor it a bit with one more BDD function i.e. beforeEach().&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;beforeEach() is used when we want to do something before every test scenario or if something is common before every scenario.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Checking functionality of Login Page",()=&amp;gt;{

    beforeEach(Visiting the login Page,()=&amp;gt;{
        cy.visit("/");
    });

    it("Testing the only single input sign in [ Should not be possible ]",()=&amp;gt;{
        cy.get('[data-cy=inputName] input').type(" ");
        cy.get('[data-cy=inputPassword] input').type("John123");
        cy.get('[data-cy=loginButton]').click();
        cy.contains("Wrong Credentials").should('be.visible');
    })

    it("Testing with wrong details [ Should not be possible ]",()=&amp;gt;{
        cy.get('[data-cy=inputName] input').type("Johnce");
        cy.get('[data-cy=inputPassword] input').type("John123");
        cy.get('[data-cy=loginButton]').click();
        cy.url().should('include','/login');
        cy.contains("Wrong Credentials").should('be.visible');
    })

    it("Testing with Correct details [ Must redirect to Welcome modal ]",()=&amp;gt;{
        cy.get('[data-cy=inputName] input').type("John");
        cy.get('[data-cy=inputPassword] input').type("John123");
        cy.get('[data-cy=loginButton]').click(); //Correct Details
        cy.contains("Welcome to Portal");
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;One problem is solved, but we are still writing functions for logging in many times which are the same, just the value provided is different.&lt;/p&gt;

&lt;p&gt;So here, we take the help of the &lt;strong&gt;Custom Commands&lt;/strong&gt; facility provided by Cypress.&lt;/p&gt;

&lt;p&gt;Now, we will create a custom function which  will take username and password as arguments and login the user. We can add that function in commands.js inside Support directory.&lt;/p&gt;

&lt;p&gt;In your support/commands.js file inside the support folder,&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Custom login function for logging In which takes username and password as parameters.
Cypress.Commands.add('login',(Username,Password)=&amp;gt;{
    cy.get('[data-cy=inputName] input').type(Username);
    cy.get('[data-cy=inputPassword] input').type(Password);
    cy.get('[data-cy=loginButton]').click();
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Your test script will look like this,&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Here in the script, we can just call the custom login function that we made just by using cy.login(username, password). 
describe("Checking functionality of Login Page",()=&amp;gt;{

    beforeEach(Visiting the login Page,()=&amp;gt;{
        cy.visit("/");
    });

    it("Testing the only single input sign in [ Should not be possible ]",()=&amp;gt;{
        cy.login("John"," ");
        cy.contains("Wrong Credentials").should('be.visible');
    })

    it("Testing with wrong details [ Should not be possible ]",()=&amp;gt;{
        cy.login("Vedant","1234");
        cy.url().should('include','/login');
        cy.contains("Wrong Credentials").should('be.visible');
    })

    it("Testing with Correct details [ Must redirect to Welcome modal ]",()=&amp;gt;{
        cy.login("John","John123");
        cy.contains("Welcome to Portal");
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Currently, the above script will work fine if we are testing locally, but when we work on a production server or CI, There might be delays in response from backend server, Cypress might get timed out waiting for homepage to load.&lt;/p&gt;

&lt;p&gt;For dealing with this situation, we can use one command i.e,&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.wait(8000);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, cy.wait() will wait make the test to wait for constant time given as argument to wait() function.&lt;/p&gt;

&lt;p&gt;But this will make our test slower when we wait for constant time.&lt;/p&gt;

&lt;p&gt;So, the better approach here is to use aliases for waiting for request to get resolved.&lt;br&gt;
Here is an example -&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Custom login function for logging In which takes username and password as parameters and also waits for data from server.
Cypress.Commands.add('login',(Username,Password)=&amp;gt;{
    cy.server();
    cy.route("POST", Cypress.env('apiURL')+"/query").as("detailsResponse");
    cy.get('[data-cy=inputName] input').type(Username);
    cy.get('[data-cy=inputPassword] input').type(Password);
    cy.get('[data-cy=loginButton]').click();
    cy.wait("@detailsResponse").its("status").should("eq", 200); //Request Done.
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In above example, &lt;code&gt;cy.server()&lt;/code&gt; will start a mock server and will be intercepting all requests from frontend. &lt;code&gt;cy.route()&lt;/code&gt; will tell Cypress to intercept a request going on a particular route. We can mock response, status and many other parameters while intercepting a request using &lt;code&gt;cy.route()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, for waiting for a request to get resolved, we have to make alias for that route using &lt;code&gt;as()&lt;/code&gt;. &lt;code&gt;as()&lt;/code&gt; makes alias of any route with given name, which the Cypress will remember for us.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.route("POST", Cypress.env('apiURL')+"/query").as("detailsResponse");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, we can wait for this request using &lt;code&gt;cy.wait()&lt;/code&gt; by giving alias name to it and checking it's status property using &lt;code&gt;its()&lt;/code&gt; function after executing our steps.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.wait("@detailsResponse").its("status").should("eq", 200); //Request Done.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Thanks for staying with me till here, In my next article, we will be discussing more about how to test other scenarios that we face in a project.Till then, you can always check their documentation &lt;a href="https://docs.cypress.io/guides/getting-started/installing-cypress.html#System-requirements" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are interested in learning more about different test scenarios in Litmus-Portal, Checkout our Litmus-Portal-E2E Repository &lt;a href="https://github.com/litmuschaos/litmus-e2e/tree/litmus-portal" rel="noopener noreferrer"&gt;here&lt;/a&gt;  &lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Feel free to check out our ongoing project - &lt;a href="https://github.com/litmuschaos/litmus/tree/master/litmus-portal" rel="noopener noreferrer"&gt;Litmus Portal&lt;/a&gt; and do let us know if you have any suggestions or feedback regarding the same. You can always submit a PR if you find any required changes.&lt;/p&gt;

&lt;p&gt;Make sure to reach out to us if you have any feedback or queries. Hope you found the blog informative!&lt;/p&gt;

&lt;p&gt;If chaos engineering is something that excites you or if you want to know more about cloud-native chaos engineering, don’t forget to check out our &lt;a href="https://litmuschaos.io/" rel="noopener noreferrer"&gt;Litmus website&lt;/a&gt;, &lt;a href="https://hub.litmuschaos.io/" rel="noopener noreferrer"&gt;ChaosHub&lt;/a&gt;, and the &lt;a href="https://github.com/litmuschaos/litmus" rel="noopener noreferrer"&gt;Litmus repo&lt;/a&gt;. Do leave a star if you find it insightful. 😊&lt;/p&gt;

&lt;p&gt;I would love to invite you to our community to stay connected with us and get your Chaos Engineering doubts cleared.&lt;br&gt;
To join our slack please follow the following steps!&lt;/p&gt;

&lt;p&gt;Step 1: Join the Kubernetes slack using the following link: &lt;a href="https://slack.k8s.io/" rel="noopener noreferrer"&gt;https://slack.k8s.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 2: Join the #litmus channel on the Kubernetes slack or use this link after joining the Kubernetes slack: &lt;a href="https://slack.litmuschaos.io/" rel="noopener noreferrer"&gt;https://slack.litmuschaos.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/litmuschaos" rel="noopener noreferrer"&gt;
        litmuschaos
      &lt;/a&gt; / &lt;a href="https://github.com/litmuschaos/litmus" rel="noopener noreferrer"&gt;
        litmus
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Litmus helps  SREs and developers practice chaos engineering in a Cloud-native way. Chaos experiments are published at the ChaosHub  (https://hub.litmuschaos.io). Community notes is at https://hackmd.io/a4Zu_sH4TZGeih-xCimi3Q
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;&lt;a href="https://litmuschaos.io/" rel="nofollow noopener noreferrer"&gt;LitmusChaos&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://avatars.githubusercontent.com/u/49853472?s=200&amp;amp;v=4"&gt;&lt;img alt="LitmusChaos" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F49853472%3Fs%3D200%26v%3D4" width="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Open Source Chaos Engineering Platform&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://slack.litmuschaos.io" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/48844a2a28b222b400e3fbeb358770903bdcb4db693ac67fae37db71869352f6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f536c61636b2d4a6f696e2d707572706c65" alt="Slack Channel"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/litmuschaos/litmus/actions/workflows/push.yml/badge.svg?branch=master"&gt;&lt;img src="https://github.com/litmuschaos/litmus/actions/workflows/push.yml/badge.svg?branch=master" alt="GitHub Workflow"&gt;&lt;/a&gt;
&lt;a href="https://hub.docker.com/r/litmuschaos/chaos-operator" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2a2ae2b0d21ae55811e5da33f40b76a4aa18cd37d027ab13c5f3a4b6230ef55b/68747470733a2f2f696d672e736869656c64732e696f2f646f636b65722f70756c6c732f6c69746d75736368616f732f6368616f732d6f70657261746f722e737667" alt="Docker Pulls"&gt;&lt;/a&gt;
&lt;a href="https://github.com/litmuschaos/litmus/stargazers" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e87b930f5b0b40039776ad0d255d62735311c7d7228bb7615d7408161915c0b2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f6c69746d75736368616f732f6c69746d75733f7374796c653d736f6369616c" alt="GitHub stars"&gt;&lt;/a&gt;
&lt;a href="https://github.com/litmuschaos/litmus/issues" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2f66885a8b6af96fe90f93b8aa9085f6065fb43e9c0a4a602219a01e7a142548/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f6c69746d75736368616f732f6c69746d7573" alt="GitHub issues"&gt;&lt;/a&gt;
&lt;a href="https://twitter.com/LitmusChaos" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/6425eb889e05cdadcf0db2a952db7e9dda44ca3df091c5ca9feea8515a2ac44f/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f6c69746d75736368616f733f7374796c653d736f6369616c" alt="Twitter Follow"&gt;&lt;/a&gt;
&lt;a href="https://www.bestpractices.dev/projects/3202" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a8d5ed826be562a3339ce503c6ff3f4ab2cc63227b18ba5f65648fdb3ca04eec/68747470733a2f2f7777772e626573747072616374696365732e6465762f70726f6a656374732f333230322f6261646765" alt="OpenSSF Best Practices"&gt;&lt;/a&gt;
&lt;a href="https://app.fossa.io/projects/git%2Bgithub.com%2Flitmuschaos%2Flitmus?ref=badge_shield" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/848851b5714a120bc84e06ebdb121f455a4a472a782a90d6f4efb681fa9be392/68747470733a2f2f6170702e666f7373612e696f2f6170692f70726f6a656374732f6769742532426769746875622e636f6d2532466c69746d75736368616f732532466c69746d75732e7376673f747970653d736869656c64" alt="FOSSA Status"&gt;&lt;/a&gt;
&lt;a href="https://www.youtube.com/channel/UCa57PMqmz_j0wnteRa9nCaw" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8420bd8ea7dfc02f130445cdcf5f3adec631ea57f9682afc56af5940cc5ca044/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f596f75547562652d5375627363726962652d726564" alt="YouTube Channel"&gt;&lt;/a&gt;
&lt;a href="https://gurubase.io/g/litmuschaos" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/d14b84f34d827a00ea3da041c025456fa77e2143b06396c17636f4531500eb23/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f47757275626173652d41736b2532304c69746d75734368616f73253230477572752d303036424646" alt="Gurubase"&gt;&lt;/a&gt;
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;&lt;em&gt;Read this in &lt;a href="https://github.com/litmuschaos/litmus/translations/TRANSLATIONS.md" rel="noopener noreferrer"&gt;other languages&lt;/a&gt;.&lt;/em&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/litmuschaos/litmus/translations/README-ko.md" rel="noopener noreferrer"&gt;🇰🇷&lt;/a&gt; &lt;a href="https://github.com/litmuschaos/litmus/translations/README-chn.md" rel="noopener noreferrer"&gt;🇨🇳&lt;/a&gt; &lt;a href="https://github.com/litmuschaos/litmus/translations/README-pt-br.md" rel="noopener noreferrer"&gt;🇧🇷&lt;/a&gt; &lt;a href="https://github.com/litmuschaos/litmus/translations/README-hi.md" rel="noopener noreferrer"&gt;🇮🇳&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Overview&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;LitmusChaos is an open source Chaos Engineering platform that enables teams to identify weaknesses &amp;amp; potential outages in infrastructures by
inducing chaos tests in a controlled way. Developers &amp;amp; SREs can practice Chaos Engineering with LitmusChaos as it is easy to use, based on modern
Chaos Engineering principles &amp;amp; community collaborated. It is 100% open source &amp;amp; a CNCF project.&lt;/p&gt;
&lt;p&gt;LitmusChaos takes a cloud-native approach to create, manage and monitor chaos. The platform itself runs as a set of microservices and uses Kubernetes
custom resources (CRs) to define the chaos intent, as well as the steady state hypothesis.&lt;/p&gt;
&lt;p&gt;At a high-level, Litmus comprises of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chaos Control Plane&lt;/strong&gt;: A centralized chaos management tool called chaos-center, which helps construct, schedule and visualize Litmus chaos workflows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chaos Execution Plane Services&lt;/strong&gt;: Made up of a…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/litmuschaos/litmus" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>litmuschaos</category>
      <category>cypress</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
