What is a Jenkins Node?

Question
You have read about Jenkins nodes. Cloudbees uses the term.

You have heard of the term "Jenkins slave" servers (which are configured to use their CPU and RAM according to the main Jenkins server's needs). What is a Jenkins node?

Answer
A Jenkins node is a Jenkins slave server.

The main Jenkins website defines a node as "A machine which is part of the Jenkins environment and capable of executing Pipelines or Projects. Both the Master and Agents are considered to be Nodes." For more information, see this posting.

From time-to-time in the I.T. field, the term "slave" (e.g., master-slave gates or master-slave flipflops) is shunned as offensive. For example CNN.com had an article that reported that some people were going to abandon the term master-slave in computers in 2002. Here are two articles that discuss the controversy of the teriminology:

http://www.seattlepi.com/national/article/Master-slave-named-most-politically-incorrect-1161133.php
https://www.theregister.co.uk/2018/09/11/python_purges_master_and_slave_in_political_pogrom/

You may also want to see this posting.

How Do You Troubleshoot the Python Message “ImportError: No module named setuptools”?

Problem scenario
You try to run sudo python setup.py build but you encounter a problem. You get a message that says "ImportError: No module named setuptools". What should you do?

Solution
If you are running Debian/Ubuntu Linux, run this: sudo apt-get -y install python-setuptools

If you are running CentOS/RedHat/Fedora Linux, run this: sudo yum -y install python-setuptools

How Do You Get Apache Tomcat to Work from the Source Installation Media?

Problem scenario(s)
One of the following problems apply.

1. You are trying to start Tomcat on Linux (e.g., with bash catalina.sh start) and you get this error:

java.lang.ClassNotFoundException: org.apache.catalina.startup.Catalina
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at org.apache.catalina.startup.Bootstrap.init(Bootstrap.java:262)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:444)

* OR *
2. You have nothing installed on Linux yet. You want to install Apache Tomcat from the source (not binary) installation media here. What should you do?

Solution

Prerequisite
Install Java. If you need assistance, see this posting.

Procedures
1.a. Go here: https://tomcat.apache.org/download-90.cgi
Look under "Source Code Distributions" to find the link for the .tar.gz file.

1.b. Download it to the Linux server. It will be something like this:
curl -k http://ftp.wayne.edu/apache/tomcat/tomcat-9/v9.0.22/src/apache-tomcat-9.0.22-src.tar.gz > /tmp/apache-tomcat-9.0.22-src.tar.gz

1.c. Copy the installation media to the /opt/ directory. Here is an example command:
sudo cp /tmp/apache-tomcat-9.0.22-src.tar.gz /opt/

1.d. Expand the content in /opt/. Here are some commands to possibly help you with this:
cd /opt/
sudo tar -zxvf apache-tomcat-9.0.22-src.tar.gz
sudo mv apache-tomcat-9.0.22-src tomcat9

2.a. The catalina.sh file in the "bin" subdirectory of the directory just created from the "tar" command should have certain settings. It needs to be executable by the user that will start the Tomcat service. You may need to use the chmod command accordingly.

2.b. If you know the JRE_HOME variable setting, skip this step. To mentally determine the JRE_HOME directory run this long command:

which java | xargs ls -lh | awk '{print $NF}' | xargs ls -lh | awk '{print $NF}' | xargs ls -lh | awk '{print $NF}' | xargs ls -lh | awk '{print $NF}' | xargs ls -lh

Take the file path that results from the above command and remove the "bin/java" part. The resulting string is what the JRE_HOME environment variable should be, but it can be desirable to set it in the catalina.sh file exclusively (and not set it as an environment variable).

2.c. Modify the …/tomcat9/bin/catalina.sh file so one line (we recommend line 154 if you are not sure) so it has this JRE_HOME assignment. As of August 14, 2019 with Tomcat version 9.0.22 it will be immediately below a comment line in the catalina.sh file that has as this text:

# For Cygwin, ensure paths are in UNIX format before anything is touched

The line that gets this assignment (as of 8/14/19 it is line 154) should have the appropriate JRE_HOME value. (In this example of the assignment, the "/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java" is the result of the command run in 2.b. above):

JRE_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/

Notice the "bin/java" was truncated from the assignment above. As we know this catalina.sh file may change, we know the assignment cannot be too high (early) or too low (late) in the script for Tomcat to start properly. Here are line numbers and a line above and below the stanza to give you context:

154 # For Cygwin, ensure paths are in UNIX format before anything is touched
155 JRE_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/
156 if $cygwin; then

3. Create a "temp" directory in the Apache Tomcat directory (e.g., /bin/apache-tomcat-9.0.22.src/temp/ or /opt/tomcat9/temp). It will be a sibling directory of the "bin" directory as referred to earlier. Modify the "temp" directory so it has very open permissions. We recommend this on the newly created file (but for security reasons you may not be allowed to do this): sudo chmod 777 temp

4. In the Apache Tomcat directory (e.g., /opt/tomcat9/ or /bin/apache-tomcat-9.0.22.src) create a lib directory. Here is how you would do it: mkdir lib

5. In the Apache Tomcat directory (e.g., /opt/tomcat9/ or /bin/apache-tomcat-9.0.22.src) create a logs directory. sudo mkdir /opt/tomcat9/logs
Give it 755 permissions with this command: sudo chmod 755 /opt/tomcat9/logs

6. Make sure the permissions on this directory allow the user that will start the Tomcat service (e.g., run the catalina.sh script) can read the files therein. Use chmod accordingly.

7.a. Download the binary media for Tomcat for the exact same version of Tomcat (e.g., 9.0.22). You will still use the source installation media primarily. But you need some .jar files. The binary installation media can be found here (in a .tar.gz file) under the "Binary Distributions" heading and under the "Core" subheading. Once you download the .tar.gz file to the Linux server, use tar -zxvf nameOf.tar.gz to extract the contents. Freely change the permissions on the folders thus created as you will delete them (e.g., once you change directories to be inside the newly created directory of extracted files, run a command like this chmod 777 lib && chmod 777 bin).

7.b. Retrieve the .jar files in the lib directory of the binary installation media and place them in the lib directory created in step #4. Take all the .jar files from the lib directory therein and copy them to the lib directory in the Apache Tomcat directory (e.g., /opt/tomcat9/lib/ or /bin/apache-tomcat-9.0.22.src/lib/).

These are suggested commands:
sudo mkdir /opt/tomcat9/lib
cd lib # where lib is the directory that was extracted with step #7.a.
sudo cp -r * /opt/tomcat9/lib

7.c. Go to the "bin" subdirectory of the files expanded from the binary installation media (the .tar.gz file). Copy "bootstrap.jar" and the "tomcat-juli.jar" to .jar files and place them in the "bin" subdirectory referred to in step #2.a.

These are suggested commands:
sudo cp tomcat-juli.jar /opt/tomcat9/bin/
sudo cp bootstrap.jar /opt/tomcat9/bin/

7.d. Delete the directory extracted from 7.a.

8. Now start Tomcat (e.g., with sudo bash /opt/tomcat9/bin/catalina.sh start). Find the Linux server's external IP address if you do not know it with this command: curl http://icanhazip.com

9. Craft a URL like this: http://x.x.x.x:8080 where x.x.x.x is the Linux server's IP address. Go to this URL from a web browser to test out your Apache Tomcat installation.

How Do You Troubleshoot The Message “Error from server (NotFound): the server could not find the requested resource”?

Updated 9/20/19

Problem scenario
You run the kubectl command. You receive "Error from server (NotFound): the server could not find the requested resource." How do you resolve this?

Solution
1.a. Run this command: kubectl version | grep Version

Look at the GitVersion values for the client and server. They should match or nearly match. (You do not necessarily want the latest version for the client. It is easier to upgrade the client version than the server version.)

1.b. This is an optional step if you are not sure if the kubectl client version is a very different version from the server version. If the output looks too busy you can try either or both of these commands:

kubectl version | grep Version | awk '{print $5}' 
kubectl version | grep Version | awk '{print $4}'

The minor versions (the one in between the decimal points like the "15" in 1.15.4), should be within one number of each other. The kubectl command can work if the difference is more than one, but when the value is six or more (or even two or more), you may get this "Error from server (NotFound): the server could not find the requested resource" message. (For clarity, "very different" means that the minor versions differ by two or more. Some variances greater than this can be tolerated, but do not expect it to work when the difference is more than two.) The error message that you received is likely due to the minor versions of the client and server being too far apart. (If they are the same or within one of each other, this solution will not help you.) The rest of this solution is about downloading a kubectl client binary file that is a version that is closer to the server's version and using it.

2. Make a copy of the kubectl file (e.g., to your home directory). This way you can rollback to it if you have to back out of this change. Download the kubectl that is consistent with the server version. Replace X.Y.Z with the server's version (as seen in the output of the command shown in 1.a. above) in the following commands:

cd /tmp/
curl -LO https://storage.googleapis.com/kubernetes-release/release/vX.Y.Z/bin/linux/amd64/kubectl

# An example of the above URL may be https://storage.googleapis.com/kubernetes-release/release/v1.15.5/bin/linux/amd64/kubectl # where 1.15.5 is the version associated with the "kubectl version" output for Server Version.

3. Place this kubectl file where the original kubectl file was (e.g., use sudo mv -i /tmp/kubectl /usr/bin/).

4. Run this command: sudo chmod 777 /usr/bin/kubectl

To read more about the implications of doing this (as it it could allow other users on the server to run kubectl), see this posting.

5. You are done. Now run the kubectl commands (e.g., kubectl get pods, kubectl get svc).

How Do You Troubleshoot no_manifest Being Returned by a “puppet master –configprint manifest” Command?

Problem scenario

From the Puppet master server you run this command: puppet master --configprint manifest

But it returns "no_manifest"

Manifests are working. Puppet agent nodes are receiving the changes of manifests on the Puppet master server.

This command seems to work perfectly (except for the manifest line): puppet master --configprint all

What is wrong?

Solution

Possible solution #1
The root cause could be a permissions issue. Use sudo before the command. sudo puppet master --configprint manifest

(We think that Puppet ought to engineer a change in future versions. Specifically we think this command would be much more useful if there was a display about what user, either one with sudoers privileges or without sudoers privileges, ran the command in the results.)

Possible solution #2
This is if your Puppet Master server has never worked.

Run this command:
sudo puppet master --configprint all | grep -i basemodule

You will see something like this:
basemodulepath = /etc/puppet/code/modules:/usr/share/puppet/modules

Mentally take the path from root "/" through "code". This will be the base. Change directories into this directory.

cd /etc/puppet/code
sudo mkdir -p environments/production/manifests/

Now you should be able to run sudo puppet master --configprint manifest

How Do You Install Katello (and Foreman) on a Linux Server?

Problem scenario
You have heard of a Foreman plugin called Katello that supports Red Hat subscription and repository management. Katello supports other plugins such as Pulp (for downloading content) and Candlepin (for managing the meta aspects of the subscriptions themselves). How do you install Katello?

Solution
Warning 1: This works for CentOS. It may work for Fedora. It will not work for RHEL; there are many dependencies for RHEL that are best handled by a satellite subscription.

Warning 2: This will obliterate a Puppet Master installation. If you have Puppet Master installed, only proceed if you do not mind starting over with configuration. This will wipe out existing Puppet Master configuration on the server with which you follow these directions.

Prerequisites
i. Your server must have 8 GB of memory. It may or may not be from a combination of swap space (virtual memory) and real memory; to create swap space, see this posting. For directions on resizing a server's memory, see this posting for a GCP server and this posting for an AWS instance.

ii. Install Puppet Master. You can follow these directions if you are using CentOS or Fedora.

Procedures

1. Run these commands (or remove the sudo from each one, create a script and run it with "sudo bash nameofscript.sh"):

sudo rpm -ivh https://fedorapeople.org/groups/katello/releases/yum/3.9/katello/el7/x86_64/katello-repos-latest.rpm

sudo rpm -ivh http://yum.theforeman.org/releases/latest/el7/x86_64/foreman-release.rpm

sudo yum -y install foreman-release-scl

sudo yum -y update

sudo yum -y install katello ntp

2. Run this command, but substitute "strongpassword" with the password of your choice:

sudo foreman-installer --scenario katello --foreman-admin-username admin --foreman-admin-password strongpassword

3. Run this command, but substitute "strongpassword" with the password of your choice, 12345 with the TCP port number of your choice, and x.x.x.x with the FQDN or external IP address of your server:

sudo foreman-installer --scenario katello --katello-proxy-url http://x.x.x.x --katello-proxy-port 12345 --foreman-admin-username admin --foreman-admin-password strongpassword

4. Open a web browser. Go to http://x.x.x.x where x.x.x.x is the external IP address. Enter it with the credentials recently provided.

How Do You Install AppArmor on a Debian or Ubuntu Linux server?

Problem scenario
You want to protect your Debian/Ubuntu Linux server. You do not want to run SELinux. What should you do?

Solution
Run this command:
sudo apt install apparmor-profiles

Check the status with this command:
sudo apparmor_status

You are done. If you want to learn more go to this site.


AppArmor comes installed and configured with many Debian distributions of Linux. SELinux can be difficult to install and configure on a Debian distribution; SELinux is made by Red Hat.

These sources say SELinux can be difficult to use with a Debian distribution:
https://www.reddit.com/r/linuxquestions/comments/nq741n/setting_up_a_separate_home_partition_to_work_with/

https://linuxconfig.org/how-to-disable-enable-selinux-on-ubuntu-20-04-focal-fossa-linux

What Do You Do when an Ansible Playbook is Not Getting a Variable Assigned Properly?

Problem scenario
Ansible variables are not being picked up when the playbook runs. You may get no errors, or you may get errors like these:

"ERROR! Syntax Error while loading YAML…did not find expected key"

"ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path"

What should you do?

Possible Solution #1
Are you using the -i flag when you are running the command to execute the playbook? Did you recently start using a role instead of a playbook? The -i flag will prevent Ansible from looking in certain directories for an "all" file or "main.yml" file. If newly added variables are not being picked up, do you have them in different files? You may need to stick with one source file that works or change the directory from which you are running the playbook.

You may also want to see these links:
https://stackoverflow.com/questions/47159193/why-does-ansible-show-error-no-action-detected-in-task-error
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html

To learn about variable precedence, see this link.

Possible Solution #2
Put the end quotes at the end of the string rather than around the closing braces }}. Here is a line that would throw the error:
"{{ variable1 }}"/subdirectory/path/to/file

Here is a line that would not throw the error:
"{{ variable1 }}/subdirectory/path/to/file"

Possible Solution #3
From a pragmatic perspective, you may want to put the variables in a playbook and not in a role. This may help you avoid this error.

Possible Solution #4
You may want to view this posting when there are no visible errors when the playbook runs.

What Should You Do to Set Firefox to Be Your Default Browser in Windows 10?

Problem scenario
When you open Firefox in Windows 10 you get a prompt about whether or not it should be your default browser. You choose the option ("Use Firefox as my default browser") to make it your default browser, but it does not work. You see a window called "Settings" which has options for default applications.

What should you do to get Firefox to be your default browser in Windows 10?

Solution
(You can replace "Firefox" with "Chrome" if you want "Chrome" to be your web browser.) The solution is slightly counter-intuitive. If you want to set Firefox as your default app, in Settings* (this application window should appear after you click "Use Firefox as my default browser"), click on the default web browser (e.g., Microsoft Edge). The icon of the web browser that is your "Default app" is what you need to click on. Then choose from the following pop-up "Firefox".

If you want to select certain files to be associated with Firefox and not others do the following steps in the * below.

*In the Settings window, go to "Set defaults by app". Find Firefox. Click on it. Click "Manage". You will see various file extensions such as .htm, .html, .shtml, .xht etc. Click the icon of the web browser that is currently associated with the file, then click on "Firefox" that appears as a choice.

  • If "Settings" is not apparent, go to the circle in the left hand corner and search for "Settings". It is referred to as a "Trusted Microsoft store app." Open "Settings".

What is a ReplicationController in Kubernetes?

Question
What is a ReplicationController in Kubernetes?

Answer
It is a component that ensures the pods are constantly running (page 90 and 91 of Kubernetes in Action by Luksa). They were designed to create and manage redundant pods (page 91 of Kubernetes in Action by Luksa). They do just that -- they do not transfer pods but create new ones on different nodes (page 93 of Kubernetes in Action by Luksa).

There are three parts to ReplicationControllers: a label selector, a replica count, and a pod template (page 92 of Kubernetes in Action by Luksa).

They are created with a JSON or YAML file (page 93 of Kubernetes in Action by Luksa). If you post this file to the Kubernetes API server, a ReplicationController will be created and pods according to its specification including the number of pods, their label(s), the image of the container for the pods, and the container port values (page 94 of Kubernetes in Action by Luksa).