Skip to content

Commit

Permalink
Cleaned README and Makefile
Browse files Browse the repository at this point in the history
  • Loading branch information
ansiblejunky committed Jan 20, 2025
1 parent 2e307da commit cafa102
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 172 deletions.
76 changes: 34 additions & 42 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,38 +1,17 @@
# Ansible Automation Platform - Makefile for Execution Environments
# Original version found on ansiblejunky @ https://github.com/ansiblejunky/ansible-execution-environment

# https://ario.cloud/posts/ansible-builder-ee
# https://earthly.dev/blog/docker-and-makefiles/

# Best practices for building images that pass Red Hat Container Certification
# https://developers.redhat.com/articles/2021/11/11/best-practices-building-images-pass-red-hat-container-certification
# Makefile Tutorial
# https://makefiletutorial.com/

# Update the tag each time you build a new image
# Update defaults
TARGET_TAG ?= v5

# Default settings
CONTAINER_ENGINE ?= podman
VERBOSITY ?= 3
SOURCE_HUB ?= registry.redhat.io
SOURCE_USERNAME ?= jwadleig
SOURCE_TOKEN ?= ${ANSIBLE_HUB_TOKEN}
#SOURCE_USERNAME ?= jwadleig
TARGET_HUB ?= quay.io
TARGET_USERNAME ?= jwadleig
#TARGET_USERNAME ?= jwadleig
TARGET_NAME ?= ansible-ee-minimal

# IMPROVEMENTS ...
#TODO: Remove TARGET_USERNAME somehow?
#TODO: Test if galaxy tokens are valid/expired before building
#TODO: See about adding info (LABELS) to the released image on Quay.io (packages, ansible-core version, collections, python deps, etc)
#TODO: Raise error when "Warning" is shown from introspect command in build section
#TODO: Decide to include scanning of original container image from Red Hat
#curl -o `basename $IMAGE_NAME`.json https://quay.io/api/v1/repository/$IMAGE_NAME/manifest/$IMAGE_DIGEST/security?vulnerabilities=true
# Workaround using `--raw` to get digest https://github.com/containers/skopeo/issues/634
# digest := $(shell (skopeo inspect --raw docker://$(BASE_IMAGE) | jq -r .manifests[].digest))
# check: # Check base images for security vulnerabilities
# @echo "\n\n***************************** Checking... \n"
# skopeo login $(BASE_REGISTRY)
# echo $(digest)

.PHONY : header clean lint check build scan test publish list shell
all: header clean lint build test publish
Expand All @@ -42,17 +21,31 @@ header:

clean: # Clean temporary files, folders and images
@echo "\n\n***************************** Cleaning... \n"
rm -rf context
rm -rf ansible-navigator.log
rm -rf \
context \
ansible-navigator.log \
ansible-builder.log \
ansible-builder.bak.log \
collections
$(CONTAINER_ENGINE) image prune -a -f

lint: # Lint the repository with yamllint
@echo "\n\n***************************** Linting... \n"
yamllint .

token: # Test token
@echo "\n\n***************************** Token... \n"
ifndef SOURCE_TOKEN
$(error The environment variable ANSIBLE_HUB_TOKEN is undefined and required)
endif
envsubst < files/ansible.cfg.template > ./ansible.cfg
mkdir collections
ansible-galaxy collection download -r requirements.yml -p collections/


build: # Build the execution environment image
@echo "\n\n***************************** Building... \n"
$(CONTAINER_ENGINE) login -u $(SOURCE_USERNAME) $(SOURCE_HUB)
$(CONTAINER_ENGINE) login $(SOURCE_HUB)
if [ -a ansible.cfg ] ; \
then \
echo "Using existing ansible.cfg"; \
Expand Down Expand Up @@ -85,10 +78,21 @@ test: # Run the example playbook using the built container image
--mode stdout \
--execution-environment-image $(TARGET_NAME):$(TARGET_TAG)

info: # Produce information about the published container image that can be used as the README in AAP
@echo "\n\n***************************** Image Layers ... \n"
$(CONTAINER_ENGINE) history --human $(TARGET_NAME):$(TARGET_TAG)
@echo "\n\n***************************** Ansible Version ... \n"
$(CONTAINER_ENGINE) container run -it --rm $(TARGET_NAME):$(TARGET_TAG) ansible --version
@echo "\n\n***************************** Ansible Collections ... \n"
$(CONTAINER_ENGINE) container run -it --rm $(TARGET_NAME):$(TARGET_TAG) ansible-galaxy collection list
@echo "\n\n***************************** Python Modules ... \n"
$(CONTAINER_ENGINE) container run -it --rm $(TARGET_NAME):$(TARGET_TAG) pip3 list --format freeze
@echo "\n\n***************************** System Packages ... \n"
$(CONTAINER_ENGINE) container run -it --rm $(TARGET_NAME):$(TARGET_TAG) rpm -qa

publish: # Publish the image with proper tags to container registry
@echo "\n\n***************************** Publishing... \n"
$(CONTAINER_ENGINE) login -u $(TARGET_USERNAME) $(TARGET_HUB)
$(CONTAINER_ENGINE) login $(TARGET_HUB)
$(CONTAINER_ENGINE) tag \
$(TARGET_NAME):$(TARGET_TAG) $(TARGET_NAME):latest
$(CONTAINER_ENGINE) tag \
Expand All @@ -104,17 +108,5 @@ publish: # Publish the image with proper tags to container registry
$(CONTAINER_ENGINE) push \
$(TARGET_HUB)/${TARGET_NAME}:latest

info: # List information about the published container image
@echo "\n\n***************************** Image Layers ... \n"
$(CONTAINER_ENGINE) history --human $(TARGET_NAME):$(TARGET_TAG)
@echo "\n\n***************************** Ansible Version ... \n"
$(CONTAINER_ENGINE) container run -it --rm $(TARGET_NAME):$(TARGET_TAG) ansible --version
@echo "\n\n***************************** Ansible Collections ... \n"
$(CONTAINER_ENGINE) container run -it --rm $(TARGET_NAME):$(TARGET_TAG) ansible-galaxy collection list
@echo "\n\n***************************** Python Modules ... \n"
$(CONTAINER_ENGINE) container run -it --rm $(TARGET_NAME):$(TARGET_TAG) pip3 list --format freeze
@echo "\n\n***************************** System Packages ... \n"
$(CONTAINER_ENGINE) container run -it --rm $(TARGET_NAME):$(TARGET_TAG) rpm -qa

shell: # Run an interactive shell in the execution environment
$(CONTAINER_ENGINE) run -it --rm $(TARGET_NAME):$(TARGET_TAG) /bin/bash
184 changes: 54 additions & 130 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,131 +1,65 @@
# Ansible Execution Environments Demo
# Ansible Execution Environment

Basic information to help you get familiar with Ansible Execution Environments and the latest Ansible Automation Platform.

General information on [Ansible Controller](https://docs.ansible.com/automation-controller/latest/html/userguide/index.html) and the related [execution environments](https://docs.ansible.com/automation-controller/latest/html/userguide/ee_reference.html).
Example repository to build Ansible Execution Environments using a Makefile.

## Quick Start

- Navigate to build server
- Optionally provision build server using [script](files/provision.sh)
- Clone down this repository
- Customize
- Edit dependencies `requirements.yml`, `requirements.txt`, `bindep.txt`
- Update tokens
- Set token environment variable `ANSIBLE_HUB_TOKEN`
- Edit `execution-environment.yml` accordingly
- Edit `Makefile`
- Edit `Makefile` variables
- Cleanup with `make clean`
- Test token with `make token`
- Build it `make build`
- Test it `make test`
- Inspect it `make inspect`
- Review it `make info`
- (Optional) Look inside `make shell`
- Publish it `make publish`
- Destroy Vagrant machine `vagrant destroy`
- Enjoy your day

## Requirements

### Build server

This repository uses `vagrant` to spin up a RHEL server and then [provisions](files/provision.sh) it.

```shell
# Start vagrant machine
vagrant up
# Connect to vagrant machine
vagrant ssh
# Prepare Ansible environment
source ~/ansible/bin/activate && cd /vagrant
```

### Tokens

To access the Ansible content (collections) and build execution environments, you'll need to provide authentication using a token. This is configured within the `ansible.cfg` in the root folder. To generate this file, use the template [ansible.cfg.template](./files/ansible.cfg.template) which authenticates to both Automation Hub and Ansible Galaxy. This means we will always pull from Automation Hub first, but if not found we default to using Ansible Galaxy for content.

First, set the following environment variables with the appropriate token strings. And then use the `envsubst` command to generate the necessary `ansible.cfg` file.

```shell
# Automation Hub token https://console.redhat.com/ansible/automation-hub/token
export ANSIBLE_HUB_TOKEN=

# Generate ansible.cfg file
envsubst < files/ansible.cfg.template > ./ansible.cfg
```

### Image registry

Ensure you login to the registry of choice using podman/docker command `podman login <registry_url>`

Automation Hub Registry (hub.example.com):

- Ensure docker/podman is authorized to access registry since Automation Hub uses self-signed certificates (see info at bottom of this article)
- Run the CLI login command `podman login hub.example.com:443`

Quay Registry (quay.io):

- Ensure you authorize docker/podman with this registry
- Go to https://quay.io/ and login or create an account
- Navigate to top-right for Account Settings
- Select the tool icon on the left
- Set the Docker/Podman CLI Password to enable encrypted passwords
- Generate the encryped password (re-enter the password)
- Select the option "Docker Login" or "Podman Login" to get the CLI command
- Run the CLI login command to have docker/podman authorized to pull/push images

Red Hat Registry (registry.redhat.io):

- Ensure you perform `docker login` command to authorize with this registry.
- Go to https://access.redhat.com/terms-based-registry/ and create a registry service account (if not already created)
- Drill down on existing service account
- Select the tab "Docker Login" to get the CLI command for both docker/podman
- Run the CLI login command to have docker/podman authorized to pull/push images
- [Troubleshooting Authentication Issues with registry.redhat.io](https://access.redhat.com/articles/3560571)

Docker Hub (hub.docker.com):

- Create a free account on the website
- Login to the website
- Run the CLI login command `docker login` with your credentials
## Find Base Image

## Pull the Image

Now that you have authenticated with a registry, you can pull down images from that registry. For example, you might want to pull down the Ansible base images. You can find official Ansible container images using `https://catalog.redhat.com/software/containers/search`.
You can find official Ansible container images using `https://catalog.redhat.com/software/containers/search`. Examples of typical base images:

```bash
# Pull base images for Ansible from registry.redhat.io
podman pull registry.redhat.io/ansible-automation-platform-24/ee-29-rhel8:latest
podman pull registry.redhat.io/ansible-automation-platform-24/ee-minimal-rhel8:latest
podman pull registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel8:latest

# Pull images from hub.docker.com
podman login hub.docker.com
podman pull hello-world
podman run hello-world
podman pull registry.redhat.io/ansible-automation-platform-25/ee-29-rhel8:latest
podman pull registry.redhat.io/ansible-automation-platform-25/ee-minimal-rhel8:latest
podman pull registry.redhat.io/ansible-automation-platform-25/ee-supported-rhel8:latest
```

## Build the Image

Ansible playbooks will be executed from a container image. We define our "golden" image using a build definition file named `execution-environment.yml`.
The image is built using that template file and running the `ansible-builder` tool.

Let's first define our execution environment using yaml. [Here is an example file from this repository](./execution-environment.yml).

Now let's run `ansible-builder` to create the image based on our template. Note that Podman is used by default to build images but we will use Docker instead. Also the default name and tag for the container image being built is `ansible-execution-env:latest` but it's highly recommended that you avoid using "latest" and set your own tag/version using the `--tag` argument.

```yaml
# Set tokens using environment variables
export ANSIBLE_HUB_TOKEN="token_value"

# Generate ansible.cfg using template
envsubst < files/ansible.cfg.template > ./ansible.cfg

# Test tokens
mkdir collections
ansible-galaxy collection download -r requirements.yml -p collections/
rm -rf collections

# Build the image and tag the image
ansible-builder build --verbosity 3 --container-runtime=podman --tag ansible-ee:5.0
# List images
$ podman image list
REPOSITORY TAG IMAGE ID CREATED SIZE
ansible-ee 5.0 9fec21fe39be 2 hours ago 987MB
```
## Login to Image Registry

For both the source and target registries, ensure you login to your registry of choice using `podman login <registry_url>`.

- Automation Hub Registry (hub.example.com):
- Ensure podman is authorized to access registry since Automation Hub uses self-signed certificates
- Run the CLI login command `podman login hub.example.com:443`
- Quay Registry (quay.io):
- Ensure you authorize docker/podman with this registry
- Go to https://quay.io/ and login or create an account
- Navigate to top-right for Account Settings
- Select the tool icon on the left
- Set the Docker/Podman CLI Password to enable encrypted passwords
- Generate the encryped password (re-enter the password)
- Select the option "Docker Login" or "Podman Login" to get the CLI command
- Run the CLI login command to have docker/podman authorized to pull/push images
- Red Hat Registry (registry.redhat.io):
- Ensure you perform `docker login` command to authorize with this registry.
- Go to https://access.redhat.com/terms-based-registry/ and create a registry service account (if not already created)
- Drill down on existing service account
- Select the tab "Docker Login" to get the CLI command for both docker/podman
- Run the CLI login command to have docker/podman authorized to pull/push images
- [Troubleshooting Authentication Issues with registry.redhat.io](https://access.redhat.com/articles/3560571)
- Docker Hub (hub.docker.com):
- Create a free account on the website
- Login to the website
- Run the CLI login command `docker login` with your credentials

## Scan the Image

Expand All @@ -146,22 +80,6 @@ ansible-navigator run playbook.yml --container-engine podman --execution-environ
ansible-navigator config --container-engine podman --execution-environment-image ansible-ee:5.0
```

## Publish the Image

Once you have built the image locally, tested it, and scanned it for security issues - you are now ready to publish the image to a registry of choice.

```bash
# Example using quay.io
podman login quay.io
podman tag ansible-ee:5.0 quay.io/jwadleig/ansible-ee:5.0
podman push quay.io/jwadleig/ansible-ee:5.0

# Example using onprem Automation Hub
podman login hub.example.com:443
podman tag ansible-ee:6.0 hub.example.com:443/ansible-ee
podman push hub.example.com:443/ansible-ee --remove-signatures
```

## Tips and Tricks

Building:
Expand Down Expand Up @@ -222,6 +140,13 @@ podman run -it registry.redhat.io/ansible-automation-platform-24/ee-minimal-rhel
podman run --rm <image-name> <command>
```

- Run ansible-builder:

```shell
# Build the image and tag the image
ansible-builder build --verbosity 3 --container-runtime=podman --tag ansible-ee:5.0
```

- Change the yum and pip repositories within the base images:

```shell
Expand Down Expand Up @@ -269,11 +194,6 @@ podman push <image-name> quay.io/username/myimage
The following example searches for images and then checks collections, system packages and python packages manually before we run the ansible-builder command.

```shell
# Login to vagrant build server
vagrant ssh
source ~/ansible/bin/activate
cd /vagrant
# Login to registry
podman login registry.redhat.io
# Search registry to find latest images
Expand Down Expand Up @@ -369,7 +289,11 @@ Execution Environments:

Makefiles:

- [Makefile Tutorial](https://makefiletutorial.com/)
- [Docker and Makefiles: Building and Pushing Images with Make](https://earthly.dev/blog/docker-and-makefiles/)
- [Ansible Builder and Execution Environments](https://ario.cloud/posts/ansible-builder-ee)
- [Docker and Makefiles](https://earthly.dev/blog/docker-and-makefiles/)
- [Best practices for building images that pass Red Hat Container Certification](https://developers.redhat.com/articles/2021/11/11/best-practices-building-images-pass-red-hat-container-certification)

## License

Expand Down

0 comments on commit cafa102

Please sign in to comment.