What Do You Do when an Ansible Playbook Is Not Removing a File or Directory or Unmounting a Directory when There Are No Errors?

Problem scenario
You run a playbook, and there are no errors.  But the playbook's simple logic is not working.  The file or directory is not being eliminated.  Or the unmount of the directory is not working via the mount module.  What should you do about a silently failing playbook?

Solution
1.  Verify there are no [trailing] spaces in the directory path.  If you accidentally quote a space after the last subdirectory or file, the playbook may not work but there may be no errors alerting you that it did not work.

2.  Verify the path in the playbook, i.e., that of a variable, is what you think it is.  Try to "echo" the value to a /tmp/ file to verify it is being computed and substituted consistent with what you expect.  You will have to run the playbook once purely for diagnostic purposes.

3.  Verify the playbook does not later recreate the file or mount the file/directory near the end of the playbook.  It may be that it does what you want, but near the end it independently reverts some of the deletion or unmounting.

4.  The Ansible modules are preferred to the shell commands.  If the error is difficult to troubleshoot, try the shell commands in addition to the Ansible modules.  The "ignore_errors: yes" is an attribute that can help out if the shell commands are prone to errors.  

5.  Verify the key part of the Ansible playbook is not commented out.  Maybe you need to uncomment a relevant stanza or variable assignment.

6.  It could be the root cause is purely for a Linux-related reason (if the managed node is Linux).  If you are using the mount module check the /etc/fstab or /etc/exports.  These files could be configured in a conflicting way with the playbook's operation such that there is no error, but your playbook is not doing what you want.  We do think that if the destination directory of the mount module does not work, Ansible ought to throw an error.  At the time of writing, we believe most (or all) Ansible versions will not throw an error.

7. Look at the relevant logs. See this posting if you need assistance.

8. For a guide to troubleshooting a generic Ansible playbook with no errors that is not working correctly, see this posting.

Why Is a GitLab Webhook That Integrates with Jenkins Failing with a “500 …instance_identity.InstanceIdentity.get …” error?

Problem scenario
A GitLab webhook (aka integration) fails.  It used to work as an integration mechanism with Jenkins.  The GitLab error message says:

"500 <!DOCTYPE html> ... at org.jenkinsci.main.modules.instance_identity.InstanceIdentity.get(InstanceIdentity.java:133)"

Solution
Go to the Jenkins server and reinstall the GitLab plugins.

How Do You Troubleshoot the Ansible Playbook Error “fatal: FAILED! => {“msg”: “The conditional check “?

Problem scenario
You run an Ansible playbook that uses a variable, but you get the message "fatal: FAILED! => {"msg": "The conditional check ...The error was: error while evaluating conditional (ansible_hostname == ):".  What should you do?

Solution
When testing a variable's value to another fixed string, put quotes around the string.  

Here is an incorrect example of a playbook using such a comparison:

      when: ansible_hostname == contintserver

Here is a correct example of an Ansible playbook using a string comparison:

      when: ansible_hostname == "contintserver"

To see more correct syntax and context, see this playbook:

- name: This is a test.
  hosts: contintserver
  tasks:
    - shell:  "free -m > /tmp/memory.txt"
- name: Second section.
  hosts: contintserver
  tasks:
    - shell: "echo  > /tmp/date.txt"
      when: ansible_hostname == "contintserver"

How Do You Use a Dictionary in Python?

Problem scenario
You want to use a dictionary in Python, but you do not know how. What should you do?

Solution
1.  For a very simple dictionary, you could use "{}" with no quotes.  This makes var1 a dictionary in Python:

var1 = {}

Normally with no colons, two matching curly braces would signify a set.  (You can find out more about this Python syntax here.)

2.  To really learn about dictionaries, create a file called test.py with the following content:

# The two lines below show how to create two dictionaries
dict1 = { 1:'Mark Zuckerberg', 2:'Sheryl Sandberg'}
dict2 = { 2:'Sheryl Sandberg', 1:'Mark Zuckerberg'}

# This if clause demonstrates testing the equivalence of the two dictionaries
if dict1 == dict2:
  print 'The contents of the dictionaries are identical!'
else:
  print 'The contents of the dictionaries are dissimilar.'

# This line demonstrates adding a key-value pair to a dictionary
dict1['Peter Thiel'] = 3
# This proves that dictionaries are mutable.
print dict1

3.  Run the program test.py (using python test.py) to see how Python dictionaries work.

How Do You Troubleshoot the Git Error Fatal Foobar.Git Does Not Appear to Be a Git Repository?

Problem scenario
You run a git command and you get an error like this:

"fatal: 'root/contint.git' does not appear to be a git repository
fatal: Could not read from remote repository."

The git command works on the server with the git repository.  But from another server you get the error above.  What should you do?

Solution
Find the full path to the git repo file.  Let's assume that you are using "git clone" and the full path is /var/opt/gitlab/git-data/repositories/root/.  From remote servers, you would run a command such as this:

git clone git@x.x.x.x:/var/opt/gitlab/git-data/repositories/root/contint.git

How Do You Use Amazon DynamoDB?

Problem scenario
You want to use a NoSQL solution from a public cloud provider. How do you deploy Amazon DynamoDB to try it out?

Solution
1.  Log into AWS.
2.  In the web browser, go to https://console.aws.amazon.com/dynamodb/home
3.  Click "Create table"
4.  Enter the fields as you find appropriate.  It should be self-explanatory.  Click "Create".
5.  You can now create items in the table, create new tables or create a cluster (e.g., the Amazon DynamoDB Accelerator called DAX which includes an in-memory cache service).

How Do You Troubleshoot SonarQube Not Working when the Logs Have a Comment about Not Being Able to Connect to the Database?

Problem scenario
In the SonarQube logs you get an error "java.lang.IllegalStateException: Can not connect to database.  Please check connectivity and settings (see the properties prefixed by 'sonar.jdbc')"

How do you troubleshoot this error?

Solution
1.  Verify you can ping the hostname.  

2.  Test the port with nmap (e.g., "nmap -p 1521 <databaseFQDN>" where <databaseFQDN> is the hostname of the database and 1521 is the port you configured in the stanza with "sonar.jdbc").  An intermediate firewall blocking connectivity over a specific port could cause problem.

3.  If the database is an Oracle database, test the credentials you were given.  If you do not know, see this posting.  Did you include a SID in the connection string?

How Do You Delete a Directory on Linux Server That Is Not Easily Deleted?

Problem scenario
You are trying to remove a directory.  When you run a "sudo rm -rf" command you get this error:

rm: cannot remove '/path/to/': Device or resource busy

When you run a "sudo umount /path/to/" command you get this error:

"umount.nfs: device is busy"

What should you do to eliminate the directory?

Solution
1.  Is the "/path/to/" in the "sudo umount" command identical to the path in the error message?  If so, skip to step #2.  If not, remember that if you get an error like this "'/path/to/subdirectoryname': Device or resource busy", then you need to try the umount command *with* the subdirectory.  The root cause of this is you are trying to umount a parent directory of a subdirectory that is mounted.

2.  If the directory is not unmounting and you are using the "sudo umount" command, run these two commands:  

sudo umount -f -l /path/to

# The -f flag is for force.  The -l flag will clean up references to the file system.  Using these two flags at the same time is recommended by various Linux experts when a directory will not unmount as it normally should.

sudo rm -rf /path/to

How Do You Use a Jenkins Pipeline with a Scripted Syntax?

Updated and re-tested on 9/24/19
Problem scenario
You read about what Jenkinsfiles are.  Coveros.com defines them as 'Jenkinsfiles, using a domain specific language based on the Groovy programming language, are persistent files that model delivery pipelines “as code", containing the complete set of encoded steps (steps, nodes, and stages) necessary to define the entire application life-cycle.'

You want to use a Scripted Pipeline in Jenkins (via a Jenkinsfile).  What do you do to use the Scripted DSL syntax?

Solution
Prerequisites

i.  You must have Jenkins installed.  See the posting for your type of Linux below for assistance installing Jenkins:

CentOS/RHEL/Fedora
Debian/Ubuntu

Pipeline jobs require more memory than typical Jenkins jobs.  If you need to resize your server (i.e., give it more RAM), click here if you have a server in AWS, and click here if you have a server in GCP.

If you are not using a public cloud, you may want to add physical RAM.  You may want to create virtual memory to help with performance.  To do that, see this posting.

ii.  Install the Pipeline plugin.  Log into the web UI of Jenkins as an administrator.  Go to Manage Jenkins -> Manage Plugins -> Available.  Search for "Build Pipeline."  Check the box and click "Install without restart".  Next, click the option for "Restart Jenkins..." at the bottom of the screen.

Procedures
1.  Log into the web UI for Jenkins as an administrator.
2.a.  If you see "New Item" do 2.b, otherwise do 2.c.
2.b.  Click on "New Item".
2.c.  Click on "Dashboard" if you do not see "New Item."  Then click "New Item".
3.  Enter a name in the field and the top, then click on "Pipeline".  Then click "OK".
4.a.  Scroll down to the "Pipeline" section.  
4.b.  Enter this text (which is mostly taken from this external site):

node {
    stage('Example') {
        if (env.BRANCH_NAME == 'master') {
            echo 'I only execute on the master branch'
        } else {
            echo 'I execute elsewhere'
        }
    }
} //Taken from https://jenkins.io/doc/book/pipeline/syntax/#flow-control
node {
    stage('Example1') {
        if (env.BRANCH_NAME == 'slave') {
            echo 'I only execute on the slave branch'
        } else {
            echo 'I do not execute on the slave branch.'
        }
    }
}

5.  (You can uncheck the "Use Groovy Sandbox" or leave it checked.*)  Click "Save".

6.a.  You can test it by clicking on "Build Now."

6.b.  You are done.  The Jenkinsfile should be checked into a source control repository.

6.c.  Here is optional reading if you want to learn more.

*  This is information on using the Groovy sandbox:

"Jenkins limits the execution of any Groovy script by providing a sandbox.  The option "Use Groovy Sandbox", shown below, is available in the Pipeline tab, and it allows the scripts to be run by any user without requiring administrator privileges.  In this case, the script is run only by using the internal accessible APIs (that allow you to develop your script by using Groovy).
...
When unchecked, if the script has operations that require approval, an administrator will have to provide them.  This method is known as "Script approval".  By default, all Jenkins pipelines run in a Groovy sandbox.  If the option is checked and unauthorized operations are used, the script will fail when run.  Both the whitelist and the blacklist of functions can be checked at Script Security's built-in list. Please refer to In-process Script Approval for more information on this topic."  The above quoted paragraphs were taken from Dzone.com.

How Do You Indent a Block of Lines in vi The Same Amount?

Problem scenario
You want several lines to be indented by four more spaces automatically.  You do not want to do it manually line-by-line.  How do you indent multiple lines uniformly with the same number of spaces (regardless if they are indented similarly or dissimilarly)?

Solution
1.  Open the file in vi.
2.  Enter this command and press enter afterwards (but replace "4" with the number of spaces you want in your indentation):    :set shiftwidth=4
3.  Go to the highest line that you want indented.
4.  Press the "v" key
5.  Highlight the lines you want indented by pressing the down key.  Once all the lines are highlighted, go to the next step.
6.  Press the ">" key.  (On most keyboards it is pressed by holding shift and pressing the "." (period) key.  (To unindent, reverse indent, or shift to the the left, use the "<" key.)