A JBoss Project
Red Hat

Aerogear Guides Tutorials to help get you off and running.

Digger installation guide

Digger Installation Introduction

GitHub repo with Ansible job used for Digger installation Digger Installer tool.

The AeroGear Digger project allows you to setup a service that has the capability to build mobile applications using OpenShift containers.

It is made of following components:

  • A Jenkins server that is used to run the build tasks

  • A Docker-formated image with all the required tools to build Android applications

  • macOS servers with pre-installed tools to build iOS applications (optional)

  • An Ansible based automation tool used to install and configure all the components

  • A nagios server for monitoring the digger components

  • A suite of sample Jenkinsfiles to demonstrate how to build mobile applications using Jenkins pipeline

This project is designed to be used with the RedHat Mobile Application Platform (RHMAP). However, it is possible to use it on its own as a CI/CD server to build mobile applications.

Prerequisites

The main components (jenkins, android-sdk, nagios) of the digger project are deployed to an OpenShift Container Platform. With these components installed, digger has the capability to build Android Applications. The user has the option to configure (via the digger installer) a macOS server to allow for iOS Application builds. This is an optional step and the macOS Server pre-requisites section below can be ignore if a macOS is not part of the installation.

The digger tool can be installed using the Digger Installer tool.

Before running the Digger installer, please make sure the following prerequisites are met:

General pre-requisites

Ansible 2.2.3 or higher

Digger Installer requires a version of Ansible 2.2.3 or higher on the machine that the Ansible playbook will be executed from. You can check the installed Ansible version by running ansible --version. Please check Ansible installation instructions for information on how to install.

Outbound internet access

Digger requires outbound internet access to perform npm installations. Make sure that all relevant nodes/servers have outbound internet access.

Proxy Configuration (optional)

If your environments are on a network behind a proxy, this can be configured through the installer. Digger supports HTTP proxy without authentication. Digger does not currently HTTP support proxy with authentication. See Known Issues for further details.

Java 2.2 and higher

Java is required for some configuration of Jenkins during the installation. If Jave is not present the installer will install it.

OpenShift pre-requisites

OpenShift 3.3 or higher

  • An OpenShift Container Platform, and its command line tool (oc) installed locally.

  • The OpenShift cluster should have the following PVs (Persistent Volumes) available

    • 40GB for Jenkins

    • 10GB for Android-sdk

    • 1GB for Nagios

Access to dockerhub

The installer retrieves the relevant docker formatted images from https://hub.docker.com/. Please ensure that all nodes in the OpenShift Installation have access to this site.

macOS Server pre-requisites

This is required for building iOS applications. The following specifications are recommended:

  • 4GB RAM

  • 2 Cores

  • A clean install of macOS 10.12 Sierra or cloud provider macincloud

  • 30GB minimum disk space and and additional 20GB per XCode version

The sections below outline the required state for the macOS node. Ansible requires SSH access to the macOS server in order to correctly provision the machine to support iOS builds. To enable this, it is required that a user with sudo permissions and SSH access exists on the target machine. Read the following sections and ensure these conditions are met to enable correct configuration of your macOS server via the Ansible installation.

Create SSH User

We recommended that you create a new user which will be provided to Ansible for SSH connections. An example bash script is provided to achieve this.

The provided scripts helps with creating an OSX user. Do not use these scripts without reviewing their contents as it will allow access to your machine with a default password. Change the default PASSWORD and ensure USER_ID is not assigned.

By default, this script will create a user named jenkins with a UID of 550 and add the user to the the sudoers file. The users PASSWORD variable is set by default to Password1. To enable iOS builds, this user is added to the admin group.

If using the sample script (contents provided below) you should read it carefully, understand its implications and edit it as required. The script can be downloaded for convenience and run using the following commands:

curl -O https://raw.githubusercontent.com/aerogear/digger-jenkins/master/admin/create-osx-user.sh
sudo bash create-osx-user.sh
#!/usr/bin/env bash

USERNAME="jenkins"
PASSWORD="Password1"
REAL_NAME="Jenkins Agent"
GROUP_NAME="staff"

# the first user's id is 500, second is 501 ...
# picking a big number to be on the safe side.
# You can run this one to list UIDs
#   dscl . -list /Users UniqueID
USER_ID=550

# GID 20 is `staff`
GROUP_ID=20

############### end of parameters

. /etc/rc.common
dscl . create /Users/${USERNAME}
dscl . create /Users/${USERNAME} RealName ${REAL_NAME}
dscl . passwd /Users/${USERNAME} ${PASSWORD}

dscl . create /Users/${USERNAME} UniqueID ${USER_ID}
dscl . create /Users/${USERNAME} PrimaryGroupID ${GROUP_ID}
dscl . create /Users/${USERNAME} UserShell /bin/bash
dscl . create /Users/${USERNAME} NFSHomeDirectory /Users/${USERNAME}
dseditgroup -o edit -a ${USERNAME} -t user admin
cp -R /System/Library/User\ Template/English.lproj /Users/${USERNAME}
chown -R ${USERNAME}:${GROUP_NAME} /Users/${USERNAME}

echo "${USERNAME}  ALL=(ALL:ALL) ALL" >> /etc/sudoers

echo "Done creating OSX user - you may need to restart the osx server to apply all changes for the user ${USERNAME}"
Restart the server to implement the changes made above.
Configure Remote Login

We must enable the Ansible process running remotely to execute commands on the macOS server via SSH.

Again, a sample script (contents provided below) is provided to achieve this. The USERNAME variable should match the user that was created in the previous step. It can be downloaded and executed by running the following:

curl -O https://raw.githubusercontent.com/aerogear/digger-jenkins/master/admin/enable-osx-remote-login.sh
sudo bash enable-osx-remote-login.sh
#!/usr/bin/env bash

# This script helps with enabling SSH for given OSX user.
# This script is not meant to be run in an automation. Run it manually.

USERNAME="jenkins"

# com.apple.access_ssh is a special group name on OSX.
# any user part of that group can have SSH connections in.
OSX_SSH_GROUP_NAME="com.apple.access_ssh"

systemsetup -setremotelogin on
# in order to check what groups are are there:
#   dscl . list /Groups PrimaryGroupID
# create a group for limiting SSH access
dseditgroup -o create -q ${OSX_SSH_GROUP_NAME}
# add user into this group
dseditgroup -o edit -a ${USERNAME} -t user ${OSX_SSH_GROUP_NAME}
# now, following should work  ---> ssh username@localhost

This allows the USERNAME created previously to access the server via SSH with a password. You may also choose to add a public key to the authorized_keys file for said user, with the private key of the key pair existing on the Ansible management node.

Connecting via Ansible

A number of tasks in the provision-osx Ansible role used in the installer require privilege escalation. This allows us to run commands as sudo user

The user created in the previous steps should be provided as a host variable to Ansible via ansible_ssh_user

Set ansible_sudo_pass variable or pass the --ask-sudo-pass flag when running the Ansible playbook to enable the installer to work with root permissions. This value should match the password set when creating the user.

Network access

The macOS requires a network access to the following hosts:

Table 1. Hosts and resources they provide:
Hostname Provides

https://github.com

Homebrew packages and Cocoapods

https://raw.githubusercontent.com

NVM - Node Version Manager

https://rvm.io

RVM - Ruby Version Manager

http://developer.apple.com

Apple Certificates and Xcode

https://npmjs.org

NPM packages

Other external hosts may be required depending on what other packages you specify to install.

Run the Digger Installer

To run the Digger installer, follow these steps:
  1. Clone the Digger Installer GitHub repo

  2. Make a copy of the Ansible inventory-sample file from the repo, and update it with the information about your infrastructure

    For a full list of variables that can be configured via the inventory file see the Installer Variables section.
  3. Run the playbook using the updated inventory-sample and follow the instructions printed in the terminal.:

    • Command to install digger without a macOS server

      ansible-playbook -i <your-inventory-sample> sample-build-playbook.yml --skip-tags=osx-provision
    • Command to install digger with a macOS server

      ansible-playbook -i <your-inventory-sample> sample-build-playbook.yml
  4. Carry out manual steps during the installation

    There are three points during the installation where there are manual steps required.

    1. Accepting the Android SDK Licence

    2. Copy the server’s (where ansible task are running) public ssh key to Jenkins

    3. Accept the Oracle Licence when installing Java on macOS server

      Both of these steps are required for the installation to complete successfully. At each step the Ansible Installer will pause and prompt with the required actions.

During the installation the Ansible playbook will perform the following tasks:

  • Verify and Install (if required) the minimum Java version

  • Create a project in OpenShift

  • Install Jenkins

  • Install Android SDK to a Persistent Volume

  • Configure Jenkins

  • Setup macOS Server(s) (optional depending on command used)

  • Install Nagios

  • Print url and credentials for Jenkins and Nagios

All tasks are idempotent. You can run them multiple times and they will produce the same results.

Verify The Installation

To monitor the status of the Digger components, the Digger installer will also install Nagios and several Nagios checks that monitor. At the end of the installation Ansible will trigger each of the checks and output the status of these checks. To navigate to Nagios and manually verify that all checks are passing, follow the steps below.

To verify the installation

  1. Log in to Nagios using the url and credentials outputted at the end of the installation.

  2. Navigate to the Services Link

  3. Verify that all Nagios checks are passing.

The environment specific checks carried out by Nagios are:

  • Container CPU Usage

  • Container Memory Usage

  • Container Resource Limits

  • Pod Disk Storage

The digger specific checks carried out by Nagios are:

  • Availability of the Jenkins container (pod)

  • Status of the network link between Jenkins and the macOS servers

  • Status of the Android SDK PersistentVolumeClaim

Installer Variables

This section describes all installer variables organized by tags.

For more information about these variables, see the Digger Installer repo

You must provide a value for all required variables or accept the default value.

You can specify a value using one of the following methods:

  • enter a value into the inventory file

  • specify a value on the command line

  • using an encrypted Ansible Vault file.

android-sdk

Variable name Description Default value Required

android_sdk_home

Location of Android SDK that is installed in the Android SDK container.

/opt/android-sdk-linux

No

configure-buildfarm

Variable name Description Default value Required

project_name

Name of the OpenShift project.

digger

No

add_public_key_automatically

Determines whether to add SSH public key to Jenkins configuration automatically.

true

No

jenkins_oauth_token

OAuth token

<oauth_token>

Yes, if add_public_key_automatically is set to true and enable_oauth is set to true.

concurrent_android_builds

Max. number of concurrent Android builds.

5

No

jenkins_private_key_password

Jenkins SSH private key password

None

Yes, if password protected

jenkins_private_key_path

Jenkins SSH private key location

~/.ssh/id_rsa

No

jenkins_public_key_path

Jenkins SSH public key location

~/.ssh/id_rsa.pub

No

jenkins_route_protocol

Route protocol used to connect to Jenkins

https

No

deploy-jenkins

Variable name Description Default value Required

project_name

Name of the OpenShift project.

digger

No

enable_oauth

Determines whether to enable OAuth OpenShift integration. If false, a static account will be created.

false

No

master_memory_limit

Maximum amount of memory the Jenkins master container can use.

3Gi

No

master_volume_capacity

Volume space available for data.

40Gi

No

deploy-nagios

Variables used to configure Nagios for sending alert emails.

Variable name Description Default value Required

smtp_server

SMTP server to send alert emails.

localhost

No

smtp_username

SMTP username.

username

No

smtp_password

Password of the SMTP user.

password

No

smtp_from_address

SMTP sender address.

admin@example.com

No

rhmap_admin_email

Destination address of alert emails.

root@localhost

No

jenkins_user

User who queries Jenkins during Nagios checks.

admin

No

jenkins_pass

User password for <jenkins_user>.

password

No

java

Variables used to configure JDK on the remote host that runs Jenkins CLI commands.

Variable name Description Default value Required

repo

The repository used to install JDK.

rhel-7-server-optional-rpms

No

java_version

JDK version to install.

1.8.0

No

login

Variables used to login to the OpenShift Cluster.

Variable name Description Default value Required

oc_user

OpenShift user who log into OpenShift.

Yes

oc_password

Password for <oc_user>.

Yes

login_url

URL used to log in to OpenShift.

https://localhost:8443

Yes

provision-osx

Variables used while provisioning a macOS node.

Variable name

Description

Default value

Required

ansible_become_pass

Sudo password required to perform root privileged actions on a macOS server. Typically, this is specified using the command line.

Yes

remote_tmp_dir

Location for temporary files.

/tmp

No

node_versions

A comma separated list of Node versions to install.

6

No

xcode_install_version

The version of the xcode-install tool to install.

2.2.1

No

gem_packages

A list of gem packages to install.

gem_packages:
- name: public_suffix
  version: 2.0.5
- name: xcode-install
  version: "{{xcode_install_version}}"

No

cocoapods_version

The version of the Cocoapods gem to install.

1.1.1

No

npm_packages

A list of global NPM packages to install.

npm_packages:
- name: cordova
  version: 7.0.1

No

homebrew_packages

The packages to install using Homebrew.

homebrew_packages:
- name: gpg
- name: grep
- name: jq

No

homebrew_version

The version of Homebrew to install (git tag).

1.3.1

No

homebrew_repo

The git repo for the version of Homebrew to install.

https://github.com/Homebrew/brew

No

homebrew_prefix

The parent directory for the Homebrew location.

/usr/local

No

homebrew_install_path

The location where Homebrew is installed.

<homebrew_prefix>/Homebrew

No

homebrew_brew_bin_path

The location where brew is installed.

/usr/local/bin

No

homebrew_paths

<homebrew_install_path>, <homebrew_brew_bin_path>, <homebrew_var_path>, /usr/local/Cellar, /usr/local/opt, /usr/local/share, /usr/local/etc, /usr/local/include

No

homebrew_taps

A list of Homebrew taps to add.

homebrew/core, caskroom/cask

No

xcode_install_user

Apple Developer Account username. If this is not set then Xcode is not installed.

Yes

xcode_install_password

Apple Developer Account password. If this is not set then Xcode is not installed.

Yes

xcode_install_session_token

Apple Developer Account auth cookie from fastlane spaceauth command (For accounts with 2FA enabled).

Yes

xcode_versions

A list of Xcode versions to install, can take over 30 minutes each to install.

'8.3.3'

No

xcode_default_version

The default version of Xcode to use

<xcode_version>[0]

No

apple_wwdr_cert_url

Apple WWDR certificate URL. Defaults to Apple’s official URL.

http://developer.apple.com/certificationauthority/AppleWWDRCA.cer

No

apple_wwdr_cert_file_name

Output file name of the downloaded WWDR certificate file.

AppleWWDRCA.cer

No

buildfarm_node_port

The port used to connect to the macOS node.

22

No

buildfarm_node_root_dir

Path to Jenkins root folder.

/Users/jenkins

No

buildfarm_credential_id

Identifier for the Jenkins credential object.

macOS_buildfarm_cred

No

buildfarm_credential_description

Description of the Jenkins credential object.

Shared credential for the macOS nodes in the buildfarm.

No

buildfarm_node_name

Name of the slave/node in Jenkins.

macOS (<node_host_address>)

No

buildfarm_node_labels

List of labels assigned to the macOS node.

ios

No

buildfarm_user_id

Jenkins user ID.

admin

No

buildfarm_node_executors

Number of executors (Jenkins configuration) on the macOS node. There is currently no build isolation for the macOS node. This means there is no guaranteed support for concurrent builds. This value should not be changed unless you are certain all apps will be built with the same signature credentials.

1

No

buildfarm_node_mode

How the macOS node should be utilised. The following options are available:

* NORMAL * EXCLUSIVE

Use EXCLUSIVE if you want build jobs with labels matching this node to only use this node.

NORMAL

No

buildfarm_node_description

Description of the macOS node in Jenkins.

macOS node for the buildfarm

No

project_name

The name of the digger Project in OpenShift

digger

No

proxy_host

Proxy url/base hostname to be used.

Yes if the macOS server only has outbound internet access via proxy

proxy_port

Proxy port to be used.

Yes if the macOS server only has outbound internet access via proxy

proxy_device

The proxy network device to use for proxy configuration.

Ethernet

No

proxy_ctx

A list of proxies to use.

webproxy, securewebproxy

No

buildfarm_lang_env_var

Value of LANG environment variable to set on the macOS node. CocoaPods requires a value of en_US.UTF-8.

en_US.UTF-8

No

buildfarm_path_env_var

$PATH environment variable to use in the macOS node.

$PATH:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

No

credential_private_key

Private key stored in Jenkins and used to SSH into the macOS node. If this is not set, a key pair is generated.

No

credential_public_key

Public key of the pair. If this is not set, a key pair is generated.

No

credential_passphrase

Passphrase of the private key. This is stored in Jenkins and used to SSH into the macOS node. If this is not set, the private key is not password protected.

No

Known issues

Issues with using HTTP Proxy

HTTP proxy with macOS Jenkins node

When configuring Jenkins to work behind a HTTP proxy, there is a limitation/bug in the way slave nodes use the Git plugins. This is because the slaves inherit proxy information from the master.

The result, is that a macOs node (the Jenkins slave responsible for iOS builds), will attempt to checkout application source code through a HTTP proxy address and port if one has been specified during the provisioning of Digger.

This may not be an issue if the slave exists on the same network, but could be problamatic if it exists on some external network outside the OpenShift cluster. Two potential workarounds exist:

  1. Add networking rules to allow the macOS server to route requests through the proxy. This is the recommended approach as it allows you to keep your Jenkins configuration intact.

  2. Remove the proxy configuration in Jenkins > Manage Jenkins > Manage Plugins > Advanced. If you then need to checkout source code behind a proxy for specific builds, the required configuration steps can be added to the Jenkinsfile where necessary.

HTTP proxy authentication in Android builds

When building Android apps, the pod in which the apps are built cannot use a proxy that requires authentication. This is due to a issue within Gradle.

Android SDK Manager tools don’t support HTTP proxy with authentication

When installing the Android SDK into the SDK pod during provisioning, the Android sdkmanager tools used don’t support HTTP Proxy that requires authentication.

Issues with Ansible provisioning

Encrypted private key cannot be provided in Ansible provisioning

The user’s private key cannot be encrypted when running the Ansible playbook.

Note that this does not include the key pair that should be provided when provisioning the macOS node, the private key of the macOS key pair should be encrypted with a passphrase.

To work around this you can use openssl to remove the passphrase from your key using the following command.

openssl rsa -in ~/.ssh/id_rsa -out ~/.ssh/id_rsa_new

iOS Build Limitations

No Build Isolation Support

At the moment, the iOS builds do not support isolation. This means if one iOS build process changes the settings/environment, it will impact every other iOS build processes.

No Parallel Builds Support On A Single macOS Server

Due to each iOS build needs to update some of the global configurations (like certifications, keys etc), only single iOS build can be run on a single Mac server at any given time. If you need to support parallel iOS builds, you will need to configure multiple Mac servers.

redhatlogo-wite