Initial contents of a content view

Problem: The project I support has had a static yum repository that all of the hosts point to. The developers claim that updates break their software. I am working on setting up a satellite server to replace that yum repository. I told the developers that we can control what gets updated when with content views and publishing to the different lifecycles. My biggest problem at the moment is trying create an initial content view such that is matches the packages in the yum repository as closely as possible. I am going to create a content view:
hammer content-view filter create --name “Initial Filter” --description “Initial contents equal to the yum repository”

and then add a filter rule:
hammer content-view filter rule create
–name acl-2.2.51-14,apr-1.4.8-3,apr-util-15.2-6

etc. I’m just not sure if I can specify the version on the name line or does it have to go with the --version parameter? If the latter, then I think I’m going to have to create a filter rule for every single package?

Expected outcome: Get a content view with packages as close to the ones in the yum repository as possible.

Foreman and Proxy versions: 2.1.4-1

Foreman and Proxy plugin versions:

Distribution and version: CentOS 7.6

Other relevant data:


  • You have a yum repository somewhere that you’d like to sync into Katello so that your clients can install packages from it


  • Sync the repo into Katello, by creating a Product and adding the repository to it
  • Add the repo to a content view which your clients are also associated to.
  • Publish and promote the Content View to the environment that you clients exist in

The clients will only see the content in the yum repo as it was when the content view was published. The next time you sync the repo in Library, the clients will not see any repo changes until the CV containing that repo is published+promoted to the environment of the content hosts. I don’t think filters apply to your scenario but let me know if I missed your point!

No. Not quite. Currently all of the hosts get their packages from a single host with a yum repository on it. In order to update/add a package, we first have to download it to this host and then update the repository. The developers wanted it this way, but it is making it extremely difficult for the system admnistrators to maintain updates with security fixes. I want to move us to having a satellite server that is connected to various satellite servers and control updates to the systems via content-views.
I’m trying to figure out a method to get the first content-view as close as possible to what is currently in the yum repository as possible. After I do that, then we can start adding incremental updates.

I did the following for an initial stab at it, but some of the content-views do not appear to have any packages in them (which was the reason for my other post - List Packages in a content-view.

On several hosts, I ran:
rpm -qa --queryformat ‘%{NAME} %{VERSION} %{RELEASE} %{EPOCH} %{ARCH}\n’ | grep -v gpg-pubkey | sort > /var/tmp/packages

I put those on the satellite server and combined into one file:
cat packages* | sort -u > cur-packages

Then I tried to build filter rules.
cd /var/tmp
mkdir content;cd content
cat > filter.awk << EOF
/^–.– http://.[^/]$/ { u=$3; }
/^Length: [[:digit:]]+/ { print u; }
wget -r -np --spider ${HTTP}/os/x86_64/Packages/ 2>&1 | awk -r filter.awk | xargs -I % basename % | sort -u > centos-os
CVID=$(hammer content-view list | grep el7_content | awk ‘{ print $1 }’)
hammer content-view filter create --name “OS Filter” --type rpm --inclusion false
–description “Filter for OS Paackages” --content-view ${CVID}
CVFID=$(hammer content-view filter list --content-view ${CVID} | grep -vE ‘-----|FILTER ID’ | grep OS | awk ‘{ print $1 }’)
for ARCH in x86_64 noarch i686 ; do
IFS=$’\n’; for f in $(grep ${ARCH} cur-packages) ; do
set -a rpm
IFS=’ ’ read -r rpm[{0…4}] < <(echo ${f})
if [[ $(grep -c “^${rpm[0]}-${rpm[1]:0:2}” centos-os) -gt 0 ]]; then
yum --showduplicates list available ${rpm[0]} | grep “${rpm[0]}.${rpm[4]}” |
sed -e ‘s|32:||’ -e ‘s|12:||’ -e ‘s|14:||’ -e ‘/^$/d’ -e ‘s|10:||’ -e ‘s|1:||’ -e ‘s|2:||’ -e ‘s|4:||’
sort -g -k 2,2 > ${TMPF}
set -a vers
vers=( $(awk ‘{ print $2 }’ ${TMPF}) )
l=$(echo ${#rpm[1])
j=$(echo ${#vers[@]})
while [[ $(i} -lt ${j} && -z ${CANDIDATE} ]]; do
if [[ ${rpm[1] < ${vers[${i}]:0:${l}} || ${rpm[1]} == ${vers[${i}]:0:${l}} ]]; then
if [[ -z ${CANDIDATE} ]]; then
echo “A candidate for ${rpm[0]} was not found”
echo “The chosen candidate is: ${CANDIDATE}”
hammer content-view filter rule create
–content-view-id ${CVID}
–content-view-filter-id ${CVFID}
–architecture ${ARCH}
–name ${rpm[0]}
–max-version ${CANDIDATE:0:${l}}
–min-version ${rpm[1]}
cat /dev/null > ${TMPF}
unset rpm
unset vers
hammer content-view filter rule list --content-view-id ${CVID} --content-view-filter-id ${CVFID}
hammer content-view publish --id ${CVID} --async

This appears to work fine for the CentOS repository, but I’m not getting any packages in for the saltstack , docker, or centrify repositories.

Just wondering if anyone sees a flaw in my logic?

I think you miss some understanding how Content Views and Lifecycles work in Katello. The idea is simple:

  • Each Content View is a collection of repositories (e.g. all Red Hat BaseOS repos and EPEL)
  • A Composite Content view is a collection of other Content Views
  • Each Content View Version is a immutable snapshot of a Content View, including which repositories it contained and which packages where in the repo at that time. And in the case of Composite Content Views, which Content View Versions it contained.
  • Each Lifecycle (e.g. Development, QA, Production) is assigned a single CV/CCV version.

So the point @Jonathon_Turel wanted to make is less complicated then what you are doing. In your situtation I’d do the following:

  1. Create a new product (e.g. RHEL-Static) in Katello and add the existing repo server as it’s repository (e.g. RHEL-Static-Base)
  2. You then create a new Content View (e.g. CV RHEL-Static) and add the RHEL-Static-Base repo to it.
  3. Create a new Composite Content View (e.g. COV RHEL-AppServer) and add ‘CV RHEL-Static’ to it. Promote that to the production Lifecycle you use.
  4. Associate the existing hosts to ‘COV RHEL-AppServer’ in the production lifecycle.
  5. If you want to add new updates to ‘COV RHEL-AppServer’, you can then add a new Content View to the existing Composite Content View and promote the new version it to production.

Bonus: you can also clone an existing host, then associate it with the Development lifecycle, which contains a Content View with the ‘live’ repo in the development Lifecycle.

I am trying to set up a CentOS content view, saltstack, nvidia, HPE, etc. And then a composite with all of them. The problem is trying to control the versions of applications that the client hosts will see. Right now, all of the hosts are running rpms that are part of CentOS 7.6 except the kernels have been updated to the 7.7 version. I need to have the CentOS content view set up so that it is presenting those same levels to the client servers. Once I have that accomplished, we can start updating applications a little at a time until we can get us up-to-date. Yes, I understand that I publish to the different lifecycles. But my first problem is trying to mimic as close as possible in the content view to the first level of the life cycle to what is currently on the yum repo server.

I could very well be missing a crucial point here. :slight_smile:

Then the only thing you need to do is replace the CentOS repos with the static repo’s you’re running with now. And then you can later add the CentOS repos with filter to selectively ‘allow’ updates to flow in.

But I’d do that in a later version, so you start with exactly the same environment as you have right now.

Everything has been going well so far. Just have a question on the best way to create filter rules. For example, we use saltstack with repo: salt_3003 . For that repository, for every package in it that we were using, I created a filter rule with a max and min version to allow inclusion of the current files. Just wondering if there would be a way to simply that? Maybe put in a rule for the salt rpm itself, but then specify the rest should be version that match the salt version?
For example, I did:

for PKG in salt salt-cloud salt-master salt-minion salt-ssh salt-syndic; do
   hammer content-view filter rule create \
      --architecture noarch \
      --name ${PKG} \
      --content-view-filter-id ${CVFID} \
      --content-view-id ${CVID} \
      --max-version 3003-2 \
      --min-verision 3001.1-0

I did similar rules for the other rpms in the repository. I wound up with 44 rules. Just wondering if there is a better way?