How Do You Troubleshoot Triggers in a CI/CD Pipeline That Are Not Functioning?

Problem scenario
You are using Bitbucket and Jenkins. You have configured triggers to happen on certain events. The events have happened, but you see no corresponding action, no alerts or error messages and nothing in any relevant log. What should you do?

Possible solution #1
In Bitbucket, log in. Go to the relevant repository. Then go to Settings -> Workflow -> Hooks. Enable the "Post-Receive Web Hooks." If this is disabled, the triggers may not fire when the events so configured do happen.

Possible solution #2
There are firewall rules between your Bitbucket instance and your Jenkins instance prohibiting communication. Or there is some other lack of communication between the two. Verify there is communication between the two.

Possible solution #3
Newer verisons of Bitbucket have more logging compared to older versions. If possible, you may want to upgrade your version of Bitbucket.

How Do You Troubleshoot the kubectl Message “Error from server (NotAcceptable): the server was unable to respond with a content type that the client supports”?

Problem scenario
You run a kubectl command, but you see this message:
Error from server (NotAcceptable): the server was unable to respond with a content type that the client supports

What should you do?

Solution
1. Run this command: kubectl version

There should be a "Client Version" and a "Server Version". The two are probably different. Find where your kubectl file is (e.g., in /usr/bin/) with this command: sudo find / -name kubectl

2. Back it up (e.g., sudo mv -i /usr/bin/bak.kubectl.bak). Make a mental note of this directory location.

3. Download the kubectl that is consistent with the server version. Replace X.Y.Z with the server's version 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.

4. Place this kubectl file where the original kubectl file was (e.g., /usr/bin/).

5. Now run the kubectl command (e.g., kubectl get pods, kubectl get svc).

When Performing Equivalence Operations on Each Item in a List or in a Tuple, which Process Takes Less Time in Python?

Problem scenario
You are trying to refactor Python code. There is an equivalence operation that happens ten million times. You are concerned that a tuple may be a better data structure than a list. Which would operate more quickly and how do you find out for sure?

Solution
The tuple will be faster.

Operations in a tuple are slightly faster. This program generates a list and an equivalent tuple of 10,000,000 random numbers numbers.

import datetime, random
t1 = datetime.datetime.now()

pretuplelist = []
for i in range(10000000):
   pretuplelist.append(random.randint(1,1000000))
coollist = tuple(pretuplelist)

prelist_t = datetime.datetime.now()
for i in range(10000000):
   a = pretuplelist[i]
   if (a == 47265): print("It was 47265!")

postlist_t = datetime.datetime.now()
listdiff = postlist_t - prelist_t

pretuple_t = datetime.datetime.now()
for i in range(10000000):
   b = coollist[i]
   if (b == 47265): print("It was 47265!")
posttuple_t = datetime.datetime.now()
tuplediff = posttuple_t - pretuple_t

print ("Time format is in hours:minutes:seconds:seconds_decimals")
print (listdiff)
print ("Duration for iterating through a list is above.  Duration for interating through the same exact content in a tuple is below")
print ("Time format is in hours:minutes:seconds:seconds_decimals")
print (tuplediff)

While the numbers are chosen at random the tuple and the list have the exact same content. The program iterates through the list and the tuple checking if a number is equal to 47265 (an arbitrary number). The program computes the time the operations take. The duration of the list operation is longer than the equivalent operation for the tuple (by a small amount). If performance is critical and you can work with a tuple (an immutable data structure), then you should use the tuple.

How Do You Find out What Version of Hammer Is Installed on Your Server?

Problem scenario
You believe that the Hammer CLI has been installed on your Red Hat Enterprise Linux server. But you do not know what version. What should you do?

Solution
Run this command: hammer --version

"Hammer is a powerful command-line tool provided with Red Hat Satellite 6. You can use Hammer to configure and manage a Red Hat Satellite Server either through CLI commands or automation in shell scripts. Hammer also provides an interactive shell." (This quote was taken from RedHat's site.) If you want to install Hammer again, see this posting.

How Do You Troubleshoot The Terraform Error “Authentication using either SSH …must be enabled in Linux profile”?

Problem scenario
You try to run terraform apply to create an Azure VM but you receive a message like this:

Error: Error applying plan:

1 error(s) occurred:

* azurerm_virtual_machine.myterraformvm: 1 error(s) occurred:

* azurerm_virtual_machine.myterraformvm: compute.VirtualMachinesClient#CreateOrUpdate: Failure sending request: StatusCo" Message="Authentication using either SSH or by user name and password must be enabled in Linux profile." Target="linux"

What should you do?

Solution
1. Back up your .tf file. Look at your .tf file. Find a stanza like this:

key_data = "ssh-rsa AAAAC5Mx{snip}ikjmI3w"

2. Replace "ssh-rsa AAAAC5Mx{snip}ikjmI3w" with the content of the .pub file of your choice. If you do not have one, create one by running this: ssh-keygen -t rsa -P ""
Press enter to the prompt. You should know have an id_rsa.pub file. Use the content of this file (despite it being very long) as the key_data value.

3. Run terraform init again. Run terraform apply again. Now the username as specified with admin_username in the .tf file will allow you to log into the Azure VM from the server you created the id_rsa.pub file when you use ssh. From other Windows workstations, you will probably not be allowed to log in the new Azure VM with that admin_username; so you will probably want to create some new users on the new Azure VM.

How Do You Set up Nginx as an HTTP Load Balancer for Other Instances of Nginx Running in Docker?

Problem scenario
You have many Docker containers running Nginx.  You want to leverage these instances for users to go to one web site and then be automatically routed to different underlying Nginx instances in Docker containers.  How do you create a single website for web clients to go to with a reverse proxy balancing the load behind-the-scenes?

Solution
Overview
We accomplish an example with four Docker containers each using a free version of Nginx.  One Docker container with Nginx will be the invisible landing page.  As a reverse proxy, this instance will not be visible to web users beyond typing in its URL or IP address in a web browser.  The other three Docker containers with Nginx will be websites.  The distributor Docker Nginx instance (aka reverse proxy or invisible landing page) will relay inbound connections to the other normal web severs.

Prerequisites
This assumes you have three Docker containers running Nginx and you know the internal IP addresses of each of the containers.  You can use this article to set up the Docker containers with Nginx.  When you create Docker containers with nginx, there is an --ip flag that is optional.  This is when their internal IP addresses are assigned.  These IP addresses will be necessary for this solution.  Retrieve them now.

Procedure
#1.a. For the landing page Nginx instance (to relay traffic to the three Docker containers with IP addresses), create the Docker container like this command:

docker run --name docker-nginxbalancer nginx

The Nginx instance that will function as a load balancer router (or pass-through portal reverse proxy) and distribute traffic should not be part of a user-defined network.  Nor should it have an IP address.

#1b.  Go inside the Docker container.  Modify this file: /etc/nginx/conf.d/default.conf in three ways.

#1.c.i. First find the location stanza in the server {} clause.  Comment out these two lines like this (with a "#" sign):

# root   /usr/share/nginx/html;
# index index.html index.htm;

#1.c.ii.  Second, insert this stanza beneath the commented out lines above (and before the closing brace of server "}"):

proxy_pass http://backend;

#1.c.iii  Thirdly at the very bottom of the entire file, add this block of text (but substitute the x.x.x.x, y.y.y.y, and z.z.z.z with the internal IP addresses of the three Docker containers with Nginx that will be members of the load balancer):

upstream backend {
   server x.x.x.x;
   server y.y.y.y;
   server z.z.z.z;
}

2.  Exit this Docker container.  Stop the container.  Start it again. 

3.  Summary
You are done at this point.  Now you can test it by opening a web browser and going to the URL of the landing page Nginx Docker container.  Below is for information on testing it and how it all works.

Details
The user will type in the URL or IP address with a port number for the landing page that is created by the Docker container with Nginx.  The IP address would be found by going to the Docker server and using the "curl http://icanhazip.com" command.  The port number would be found by running "docker ps -a".  This command will show a colon with two integer values in a row of data for the Docker container with the landing page.  The integer on the left of the column is the port number to uniquely identify the Nginx instance.  The socket for Nginx is the external IP address of the server with a colon and the port number (e.g., 10.10.10.10:555).  This is the URL the user will type into a web browser to get to the landing page.

Have users go to the URL that will get them to the landing page (supported by Nginx in a Docker container that was referred to in steps #1 and #2).  The clients will see only a web UI but their inbound connections will be relayed to one of the possible web servers (be that x.x.x.x, y.y.y.y, or z.z.z.z).  The requests will be distributed via a round robin method.  Behind the scenes the first web page request will go to x.x.x.x.  The second request from a client workstation will go to y.y.y.y.  The third will go to z.z.z.z.  For your edification you may want test this round robin mechanism (that happens automatically and requires no user or administrator intervention).  To do this go to the three Docker containers with Nginx serving as a regular web server via the the back-end and modify the /usr/share/nginx/html/index.html file in the Docker container itself. Go to the <h1> stanza that says "Welcome to Nginx!".  Replace the "Welcome to Nginx!" with "AAAAA", "BBBBB" or "CCCCC" (so as to uniquely identify the server when the page is rendered in a web browser).  This way you'll see the round-robin distribution as you click refresh in the web browser once you have gone to the URL that will take you to the Nginx landing page (the container that was involved in step #1 above).  You will see "AAAAA", "BBBBB" or "CCCCC" as evidence of the distribution upon each refresh.

FFR
If you want to need to troubleshoot problems with your Nginx load balancer, see this link.

How Do You Set up Nginx as an HTTP Load Balancer So Client Requests (from Web Browsers) Go to Certain Nginx Servers More Frequently Than Others?

Problem scenario
You have certain Nginx servers with ample resources whereas others have minimal resources.  Based on geographic locations and data center bandwidth locations and costs, you want to assign fractions of the web traffic from client workstations (requests from web browsers) to different Nginx servers more than others.  You do not want round-robin, equal distribution of traffic.  You want customized HTTP load balancing in accord with unequal configurations.  How do you distribute this traffic proportionately according to your desired specifications?

Solution
Prerequisite

You must have configured Nginx as an HTTP load balancer (or reverse proxy server).  To do this, see this article which will actually work for Nginx distributing traffic to regular Nginx websites, Apache websites, or Nginx websites running in Docker containers. 

Procedure
Use the "weight" keyword in the default.conf file.  Even regular Docker containers on Linux severs will still support the "find" keyword.  Therefore you can always use "find / -name default.conf" to find the Nginx configuration file.  This file should have an "upstream backend {}" section.  Here is an example:

upstream backend {
  server 10.10.10.10 weight=5;
  server 10.10.10.11 weight=4;
  server 10.10.10.12 weight=2;
  server 10.10.10.13 weight=4;
}

The higher the weight, the greater the traffic that is sent to the server.  In this instance the 10.10.10.12 server would receive half the traffic that server 10.10.10.13 would receive.  This weight directive works the same for Nginx instances running directly on a server or running in a Docker container.  The default weight is 1 (according to DigitalOcean's website).  The percentage of traffic a server will get will be its individual weight divided by the sum of all the weights of the servers in the "upstream backend {}" section.

The "weight" values with Nginx in Docker behave no differently from Ngnix running on a server directly. 

How Do You Install Hammer on Linux?

Problem scenario
You want to install the Hammer CLI on a Red Hat derivative of Linux (e.g., CentOS/RHEL/Fedora). What should you do?

Solution
Overview
"Hammer is a powerful command-line tool provided with Red Hat Satellite 6. You can use Hammer to configure and manage a Red Hat Satellite Server either through CLI commands or automation in shell scripts. Hammer also provides an interactive shell." (This quote was taken from RedHat's site.)

Prerequisite
Install Foreman if it has not been installed yet. If you need assistance, see "How Do You Install Foreman on a RHEL Server?"

Procedures
Run these commands:

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

To learn more about how to configure Hammer and use it, see these postings: