Thursday, September 30, 2021

Installing ESLint extension for VSCode

My project has ESLint configured on both the client and server code, the code is separated under to folders in the same git repository.  Command line linting worked great.  Below are quick notes on how to get the linter configured and recognized by VSCode.

  • Install the ESLint extension for Visual Studio Code.  
  • .vscode/settings.json configuration - multiple useful settings so far:
    • Because there are multiple working directories under the root project folder, must set "eslint.workingDirectories". 
      • Without setting "eslint.workingDirectories" it was only formatting one of my folders ("server").  It wasn't until "eslint.workingDirectories" was specified did it recognize other folders as well.
    • "editor.tabSize: my project uses spaces instead of tabs and two spaces by default
    • "editor.rulers":  visually see how many characters can fit on a line
    • "files.eol": CRLF or LF
    • "editor.autoIndent":  when pressing enter, auto-indent or not
    • "editor.defaultFormatter":  specify the ESLint extension installed
    • "editor.formatOnPaste"/"editor.formatOnSave"/"editor.format.enable": must be enabled to format and format on paste/save

{

  "eslint.workingDirectories":[
    "./client",
    "./server"
  ],
  "editor.tabSize":2,
  "editor.rulers":[
    120
  ],
  "files.eol":"\n",
  "editor.autoIndent":"keep",
  "[javascript]":{
    "editor.defaultFormatter":"dbaeumer.vscode-eslint"
  },
  "editor.formatOnPaste":true,
  "editor.formatOnSave":true,
  "eslint.format.enable":true
}

Warnings:

  • Before I had the VSCode settings configured properly, I kept getting "Extension 'ESlint' cannot format <file>" errors during saving. 
    • These settings were key: "eslint.format.enable", "eslint.formatOnSave", and "eslint.workingDirectories"
  • Any files/patterns that are listed in the .eslintignore files will not be able to be formatted by the IDE!!!  I had *.test.js files ignored since I wanted to fix those eslint errors/warnings later.  But then I realized I had to fix them and remove them from the ignore files if I wanted to have them fixed during save.

Helpful articles:

https://stackoverflow.com/questions/45093510/eslint-not-working-in-vs-code

https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint




Saturday, August 28, 2021

JS get variable name as string

I needed to get the variable name as a string recently, some notes to remember:

// getting variable name as string
// regular string, array, int, object
const cherryshoeTypes1 = "hi";
const cherryshoeTypes2 = ["cherry", "shoe"];
const cherryshoeTypes3 = 9;
const cherryshoeTypes4 = {name:"cherry"};

const dynamicVarName1 = Object.keys({cherryshoeTypes1})[0];
const dynamicVarName2 = Object.keys({cherryshoeTypes2})[0];
const dynamicVarName3 = Object.keys({cherryshoeTypes3})[0];
const dynamicVarName4 = Object.keys({cherryshoeTypes4})[0];

console.log(dynamicVarName1);
console.log(dynamicVarName2);
console.log(dynamicVarName3);
console.log(dynamicVarName4);

An article that was helpful:

https://stackoverflow.com/questions/4602141/variable-name-as-a-string-in-javascript

Saturday, July 31, 2021

Upgrade Nginx on CentOS/RHEL 7 from 1.16.1/1.15.2 to 1.20.1, install with Ansible

The upgrade of Nginx on CentOS/RHEL 7 from 1.16.1/1.15.2 to 1.20.1 involved a complete manual removal and ansible installation.  Complete removal and installation were used vs upgrading the version because upgrading requires Nginx modules to be upgraded separately, where an installation takes care of everything.

NOTES:

  • In my case, there were no breaking changes with the nginx.conf and cherryshoe.conf files used from the old to new versions.
  • I installed with yum several times, and on occasion the /etc/nginx/conf.d and /etc/nginx/default.d folders were not created.  You may have to add the ansible task to create these for you prior to copying over the configuration files.
Environment:
ansible 2.9.9
CentOS/RHEL 7
nginx 1.16.1/1.15.2 to 1.20.1

Uninstall existing Nginx

  1. change to the appropriate user that has access to sudo
  2. note the old version, should be 1.16.1/1.15.2
    • nginx -v
  3. stop nginx and verify it's down
    • sudo systemctl stop nginx
    • sudo systemctl status nginx
  4. remove nginx
    • sudo yum remove nginx
    • Confirm y
    • Should see something like the following:
      Loaded plugins: fastestmirror
      Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast
      Resolving Dependencies
      --> Running transaction check
      ---> Package nginx.x86_64 1:1.16.1-1.el7 will be erased
      --> Processing Dependency: nginx for package: 1:nginx-mod-http-xslt-filter-1.16.1-1.el7.x86_64
      --> Processing Dependency: nginx for package: 1:nginx-mod-http-perl-1.16.1-1.el7.x86_64
      --> Processing Dependency: nginx for package: 1:nginx-mod-stream-1.16.1-1.el7.x86_64
      --> Processing Dependency: nginx for package: 1:nginx-mod-mail-1.16.1-1.el7.x86_64
      --> Processing Dependency: nginx for package: 1:nginx-mod-http-image-filter-1.16.1-1.el7.x86_64
      --> Running transaction check
      ---> Package nginx-mod-http-image-filter.x86_64 1:1.16.1-1.el7 will be erased
      --> Processing Dependency: nginx-mod-http-image-filter = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
      ---> Package nginx-mod-http-perl.x86_64 1:1.16.1-1.el7 will be erased
      ---> Package nginx-mod-http-xslt-filter.x86_64 1:1.16.1-1.el7 will be erased
      ---> Package nginx-mod-mail.x86_64 1:1.16.1-1.el7 will be erased
      ---> Package nginx-mod-stream.x86_64 1:1.16.1-1.el7 will be erased
      --> Running transaction check
      ---> Package nginx-all-modules.noarch 1:1.16.1-1.el7 will be erased
      --> Finished Dependency Resolution
      Dependencies Resolved
      ==========================================================================================
      Package                            Arch          Version               Repository    Size
      ===========================================================================================
      Removing:
       nginx                              x86_64        1:1.16.1-1.el7        @epel        1.6 M
      Removing for dependencies:
       nginx-all-modules                  noarch        1:1.16.1-1.el7        @epel        0.0
       nginx-mod-http-image-filter        x86_64        1:1.16.1-1.el7        @epel         24 k
       nginx-mod-http-perl                x86_64        1:1.16.1-1.el7        @epel         54 k
       nginx-mod-http-xslt-filter         x86_64        1:1.16.1-1.el7        @epel         24 k
       nginx-mod-mail                     x86_64        1:1.16.1-1.el7        @epel         99 k
       nginx-mod-stream                   x86_64        1:1.16.1-1.el7        @epel        171 k
      Transaction Summary
      ===========================================================================================
      Remove  1 Package (+6 Dependent packages)
       Installed size: 2.0 M
      Is this ok [y/N]:
      
  5. delete nginx configuration and log folders
    • sudo rm -R /etc/nginx
    • sudo rm -R /var/log/nginx

Install Nginx

The ansible deploy will install nginx-1.20.1, task looks like:

The upgrade of Nginx on CentOS/RHEL 7 from 1.16.1/1.15.2 to 1.20.1 involved a complete manual removal and ansible installation.  Complete removal and installation were used vs upgrading the version because upgrading requires Nginx modules to be upgraded separately, where an installation takes care of everything.

NOTES:

  • In my case, there were no breaking changes with the nginx.conf and cherryshoe.conf files used from the old to new versions.
  • I installed with yum several times, and on occasion the /etc/nginx/conf.d and /etc/nginx/default.d folders were not created.  You may have to add the ansible task to create these for you prior to copying over the configuration files.

Uninstall existing Nginx

  1. change to the appropriate user that has access to sudo
  2. note the old version, should be 1.16.1/1.15.2
    • nginx -v
  3. stop nginx and verify it's down
    • sudo systemctl stop nginx
    • sudo systemctl status nginx
  4. remove nginx
    • sudo yum remove nginx
    • Confirm y
    • Should see something like the following:
  5. delete nginx configuration and log folders
    • sudo rm -R /etc/nginx
    • sudo rm -R /var/log/nginx

Install Nginx

The ansible deploy will install nginx-1.20.1, task looks like:

- name: install system dependencies
  yum:
    name:
      - nginx-1.20.1
    state: present
    update_cache: yes

- block:
    - name: set up nginx site conf
      template:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
      with_items:
        - { src: "cherryshoe.conf.j2", dest: "/etc/nginx/conf.d/cherryshoe.conf" }
        - { src: "nginx.conf.j2", dest: "/etc/nginx/nginx.conf" }
    - name: restart nginx
      systemd: enabled=yes state=reloaded name=nginx

Verification

  1. verify new version
    • nginx -v
  2. verify nginx configuration and log folders created
    • sudo ls -la /etc/nginx
    • sudo ls -la /var/log/nginx
  3. verify application works

Wednesday, June 30, 2021

Jmeter - incrementing user defined variables for use

I found a post from five years ago I never published, here it is!   Looks like the immediate minor version after I tested this (Jmeter 3.1), the recommendation was to switch from BeanShell lightweight scripting for java to groovy scripting.  

I had used JMeter to perform tests where the username would change based on the number of times I wanted the test case to be run.  I had five test users on my system (user1, user2, user3, user4, user5) and needed to increment the user being used for each call for variability.

Environment:
Jmeter 3.0
java version "1.8.0_66"
Windows 7

Steps:
Set Jmeter user-defined variables to start off with:


Use Jmeter's Bean Shell Pre Processor to set and increment two user-defined variables USER_TO_INCREMENT and INCREMENT_NUM.  The script:
- grabs the current value of INCREMENT_NUM, which at the start is 0
- checks if the INCREMENT_NUM value is less than 5, if so will increment the value by 1, else will reset the number to 1
- saves the new USER_TO_INCREMENT and INCREMENT_NUM values to the user-defined variables


Now, for subsequent HTTP calls the USER_TO_INCREMENT and INCREMENT_NUM variables will be used.

Sunday, May 16, 2021

Ansible - create user with no password but can only login with su

This user "cherryshoe_admin" is only used after I log into the system as myself first with "cherryshoe", and then switch to this user to perform certain tasks such as running application services.  Because the "cherryshoe_admin" user is meant to have no password, the ansible user module creates the user "cherryshoe_admin" with no login shell. 

Environment:

control node OS - CentOS Linux release 7.3.1611 (Core)
control node ansible - 2.9.18
managed nodes OS - RHEL 7 (with SELinux as Enforcing)

Original ansible tasks:

- name: set up project group cherryshoe_admin
  group:
    name: "cherryshoe_admin"
    state: present

- name: set up project user cherryshoe_admin.
  user: name='cherryshoe_admin' group='cherryshoe_admin'

This exclamation points after the username show that the user is locked and "cherryshoe" is unable to su login to "cherryshoe_admin":

$ sudo cat /etc/shadow | grep cherryshoe_admin
cherryshoe_admin:!!:18739:0:99999:7:::

To fix the problem, added additional new task to explicitly force no password for user "cherryshoe_admin":

# cherryshoe_admin needs to have a login shell for su purposes, so unlock account
- block:
    - name: unlock cherryshoe_admin user account for su purposes with no password
      shell: passwd -u cherryshoe_admin -f

This shows that the user is not locked:

$ sudo cat /etc/shadow | grep cherryshoe_admin
cherryshoe_admin::18739:0:99999:7:::

As my user "cherryshoe", am now able to "su cherryshoe_admin" without a password.


P.S.  I also tried using the ansible user module to create the user with a default shell and empty password, but it creates the user as locked:

- name: set up project user cherryshoe_admin.
  user: name='cherryshoe_admin' group='cherryshoe_admin' shell=/bin/bash password=""

Sunday, April 18, 2021

Redirect users of Internet Explorer with Nginx

The project I'm on recently decided to stop Internet Explorer support.  Below is how to redirect users of Internet Explorer to a different webpage using the Nginx web server.  It allowed removing IE support configured via the React package.json browserlist attribute and removing any IE-specific polyfill code that was used.

Environment
CentOS Linux release 7.3.1611 (Core) 
React 17.1
nginx version: nginx/1.16.1

Use this outside of a server or location configuration.  Trident is to detect modern IE in compatibility mode.  The Nginx map module creates the variable $outdated based on values from the $http_user_agent variable.

map $http_user_agent $outdated {
    default              0;
    "~MSIE [1-11]\."     1;
    "~Trident/[1-7]\."    1;
}

To test it, can add a custom header inside the server or location configuration.

add_header X-debug-http_user_agent "http_user_agent $http_user_agent" always;
add_header X-debug-outdated "outdated $outdated" always;

After testing that the http_user_agent and outdated have the values you expect, then add in the redirect inside a server or location configuration.  I chose HTTP Status 307 because it's a temporary redirect and because it guarantees that the method and the body will not be changed when the redirected request is made.

if ($outdated = 1) {
    return 307 https://www.cherryshoetech.com/;
}

The package.json browserslist was updated to remove support for any version of IE.  You can test that by running "npx browserslist".

"not ie > 0"

Again, I recommend you NOT put in the redirect code until you are certain the http_user_agent and outdated variables are working as expected.  If you do, while testing during development, you will need to clear browsing data, cache, etc, as redirect headers can be cached and you may think you are getting the latest Nginx change (but you may not be).  For Internet Explorer, to turn off temporary redirect HTTP 307 while experimenting, make sure to:

Select Tools (via the Gear Icon) > Safety > Delete browsing history.... ->Make sure to uncheck Preserve Favorites website data and check both Temporary Internet Files and Cookies.

Helpful articles:

https://gist.github.com/ddre54/10996786

https://serverfault.com/a/580739

https://answers.microsoft.com/en-us/ie/forum/ie11-windows_7/redirect-loop-in-internet-explorer-11-on-this-site/10dd261a-0359-49c9-aeb4-bfed8d01ead5


Sunday, March 14, 2021

CSS - divs side by side flexbox examples

Below are examples with <div>'s side by side styled with flexbox:

  1. two <div>'s with equal widths
  2. two <div>'s one with fixed width and other expanding width
  3. three <div>'s with defined percentage widths


cherryshoe.html

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="cherryshoe.css">
<title>cherryshoe</title>
</head>
<body>
    <h3>Flexbox - divs side by side</h3>
    <p>Example 1: equal widths</p>
    <div class="container-equal">
        <div class="container-equal-child">Left 50%</div>
        <div class="container-equal-child">Right 50%</div>
    </div>
    <p>Example 2: left taking up remaining, right fixed with</p>
    <div class="container-different">
        <div class="container-different-left">Left will expand to fill space</div>
        <div class="container-different-right">Right fixed width</div>
    </div>
    <p>Example 3: with defined percentage widths</p>
    <div class="container-thirds">
        <div class="container-thirds container-thirds-child-left">Left with 20%</div>
        <div class="container-thirds container-thirds-child-center">Center with 30%</div>
        <div class="container-thirds container-thirds-child-right">Right with 50%</div>
    </div>
</body>
</html>

cherryshoe.css

.container-equal {
  display: flex; /* define flex container with default row direction */
}
.container-equal-child{
  flex: 1;  /* grow */
  background: orange;
}
.container-equal-child:first-child{
  flex: 1;  /* grow */
  background: yellow;
 }

.container-different {
  display: flex;
}
.container-different-left{
  flex: 1;  /* grow */
  background: yellow;
}
.container-different-right {
  flex: 0 0 250px; /* flex-grow 0, flex-shrink 0, flex-basis with fixed width */
  background: orange;
}

.container-thirds {
  display: flex;
  width: 100%; 
  background: yellow;
}
.container-thirds .container-thirds-child-left {
  width: 20%; 
}
.container-thirds .container-thirds-child-center {
  width: 30%; 
  background: orange;
}
.container-thirds .container-thirds-child-right {
  width: 50%; 
  background: pink;
}

Flexbox is supported in modern browsers: