Skip to content

Commit

Permalink
Add Base image and depend on it for xrootd, mon, xcache
Browse files Browse the repository at this point in the history
  • Loading branch information
juztas committed Feb 7, 2024
1 parent 30f45fd commit 1ccc187
Show file tree
Hide file tree
Showing 9 changed files with 347 additions and 4 deletions.
86 changes: 86 additions & 0 deletions .github/workflows/build-base-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Docker Image Build For Base Image

on:
workflow_dispatch:
inputs:
buildtag:
description: "Build Tag"
default: "dev"
type: "string"

jobs:
build:
runs-on: ubuntu-latest
env:
DOCKER_USER: ${{secrets.DOCKER_USER}}
DOCKER_REGISTRY: ${{secrets.DOCKER_REGS}}
DOCKER_SDN_USER: ${{secrets.DOCKER_SDN_USER}}
DOCKER_SDN_REGISTRY: ${{secrets.DOCKER_SDN_REGS}}
DOCKER_TIER2_USER: ${{secrets.DOCKER_TIER2_USER}}
DOCKER_TIER2_REGISTRY: ${{secrets.DOCKER_TIER2_REGS}}
IMAGE_NAME: "cmscaltech/base_image"
BUILD_DIR: "cmscaltech-docker/base_image"
steps:
- name: Checkout tools repo
uses: actions/checkout@v3
with:
repository: cmscaltech/docker
path: cmscaltech-docker

- name: Login to First Docker Registry
id: dockerOne
if: always()
uses: docker/login-action@v3
with:
registry: ${{secrets.DOCKER_REGS}}
username: ${{secrets.DOCKER_USER}}
password: ${{secrets.DOCKER_PASSWORD}}

- name: Login to Second Docker Registry
id: dockerTwo
if: always()
uses: docker/login-action@v3
with:
registry: ${{secrets.DOCKER_SDN_REGS}}
username: ${{secrets.DOCKER_SDN_USER}}
password: ${{secrets.DOCKER_SDN_PASSWORD}}

- name: Login to Thrid Docker Registry
id: dockerThree
if: always()
uses: docker/login-action@v3
with:
registry: ${{secrets.DOCKER_TIER2_REGS}}
username: ${{secrets.DOCKER_TIER2_USER}}
password: ${{secrets.DOCKER_TIER2_PASSWORD}}

- name: Build Docker image
id: mainRun
if: always() && (steps.dockerOne.outcome == 'success' || steps.dockerTwo.outcome == 'success' || steps.dockerThree.outcome == 'success')
run: |
cd $BUILD_DIR
docker build . --file Dockerfile \
--tag $IMAGE_NAME:${{ github.event.inputs.buildtag }} \
--tag $IMAGE_NAME:${{ github.event.inputs.buildtag }}-$(date +%Y%m%d) \
--tag $DOCKER_SDN_REGISTRY/$IMAGE_NAME:${{ github.event.inputs.buildtag }} \
--tag $DOCKER_SDN_REGISTRY/$IMAGE_NAME:${{ github.event.inputs.buildtag }}-$(date +%Y%m%d) \
--tag $DOCKER_TIER2_REGISTRY/$IMAGE_NAME:${{ github.event.inputs.buildtag }} \
--tag $DOCKER_TIER2_REGISTRY/$IMAGE_NAME:${{ github.event.inputs.buildtag }}-$(date +%Y%m%d)
- name: Docker Push Image to first registry
if: always() && (steps.mainRun.outcome == 'success' && steps.dockerOne.outcome == 'success')
run: |
docker push $IMAGE_NAME:${{ github.event.inputs.buildtag }}-$(date +%Y%m%d)
docker push $IMAGE_NAME:${{ github.event.inputs.buildtag }}
- name: Docker Push Image to second registry
if: always() && (steps.mainRun.outcome == 'success' && steps.dockerTwo.outcome == 'success')
run: |
docker push $DOCKER_SDN_REGISTRY/$IMAGE_NAME:${{ github.event.inputs.buildtag }}
docker push $DOCKER_SDN_REGISTRY/$IMAGE_NAME:${{ github.event.inputs.buildtag }}-$(date +%Y%m%d)
- name: Docker Push Image to third registry
if: always() && (steps.mainRun.outcome == 'success' && steps.dockerThree.outcome == 'success')
run: |
docker push $DOCKER_TIER2_REGISTRY/$IMAGE_NAME:${{ github.event.inputs.buildtag }}
docker push $DOCKER_TIER2_REGISTRY/$IMAGE_NAME:${{ github.event.inputs.buildtag }}-$(date +%Y%m%d)
9 changes: 9 additions & 0 deletions base_image/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM opensciencegrid/software-base:23-al8-release

RUN yum -y install python3-pyyaml && yum clean all
RUN mkdir -p /opt/usergroups && mkdir -p /opt/scripts/
ADD config/opt/usergroups/user-group /opt/usergroups/user-group
ADD config/opt/scripts/usergroupchecker.py /opt/scripts/usergroupchecker.py
RUN chmod +x /opt/scripts/usergroupchecker.py
ADD config/etc/supervisord.d/10-usergroupchecker.conf /etc/supervisord.d/10-usergroupchecker.conf

3 changes: 3 additions & 0 deletions base_image/config/etc/supervisord.d/10-usergroupchecker.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[program:usergroupchecker]
command=python3 /opt/scripts/usergroupchecker.py
autorestart=true
154 changes: 154 additions & 0 deletions base_image/config/opt/scripts/usergroupchecker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Check user and group file and create users and groups as needed"""

import sys
import os.path
import pwd
import grp
import datetime
import subprocess
import yaml

# Content of usergroup file under /etc/usergroups/user-group
#groups:
# gpuusers:
# name: 'gpuusers'
# gid: 4444
# uerj:
# name: 'uerj'
# gid: 4999
# docker:
# name: 'docker'
# gid: 5555
# allcit:
# name: 'allcit'
# gid: 6666
# sdntestbed:
# name: 'sdntestbed'
# gid: 7777
# qnet:
# name: 'qnet'
# gid: 8888
# btl:
# name: 'btl'
# gid: 9999
#users:
# jbalcas:
# username: jbalcas
# full_name: Justas Balcas
# email: [email protected]
# id: 3000
# expiry: '2024-07-01'
# dn:
# - '/DC=ch/DC=cern/OU=Organic Units/OU=Users/CN=jbalcas/CN=751133/CN=Justas Balcas'
# groups:
# - allcit
# - cms
# - gpuusers
# - sdntestbed

# Load file and check that users and groups are defined
# if not, create user and add user to group
# Also create grid-mapfile and voms-mapfile and add all users/groups as needed
def runCmd(command):
"""Run command and print output"""
process = subprocess.Popen(command,stdout=subprocess.PIPE, shell=True)
stdout, stderr = process.communicate()
exitCode = process.wait()
if stdout:
for line in stdout.splitlines():
print(line.decode('utf-8'))
if stderr:
for line in stderr.splitlines():
print(line.decode('utf-8'))
if exitCode != 0:
print(f"Error while executing command: {command}")
sys.exit(1)

def groupCheck(group, vals):
"""Check if group exists, if not, create it"""
if 'name' not in vals or 'gid' not in vals:
print(f'WARNING! Group name ir GID not defined. {group}')
return
if group != vals['name']:
print(f'WARNING! Group name does not match. {group} != {vals["name"]}')
return
try:
grp.getgrnam(group)
except KeyError:
print(f"Creating group: {vals['name']}")
# groupadd -g 3000 jbalcas
runCmd(f"groupadd -f -g {vals['gid']} {vals['name']}")

def createUser(username, uid, groups):
"""Create user and add to groups"""
try:
pwd.getpwnam(username)
except KeyError:
print(f"User does not exist. Creating user: {username}")
grLine = ",".join(groups)
if grLine:
runCmd(f"useradd -u {uid} -s /sbin/nologin -M -G {grLine} {username}")
else:
runCmd(f"useradd -u {uid} -s /sbin/nologin -M {username}")
return
# If user exists, then check if groups are correct
groups = [g.gr_name for g in grp.getgrall() if username in g.gr_mem]
gid = pwd.getpwnam(username).pw_gid
groups.append(grp.getgrgid(gid).gr_name)
if set(groups) != set(groups):
print(f"Groups are not correct. Fixing groups for user: {username}")
grLine = ",".join(groups)
runCmd(f"usermod -G {grLine} {username}")

def deleteUser(username):
"""Delete user"""
try:
pwd.getpwnam(username)
except KeyError:
print(f"User does not exist. Nothing to delete: {username}")
return
print(f"Deleting user: {username}")
runCmd(f"userdel {username}")

def userCheck(username, vals):
"""Check if user exists, if not, create it"""
action = 'create'
# If username or id is not defined, then skip
if 'username' not in vals or 'id' not in vals:
print(f'WARNING! Username ir ID not defined. {vals}')
return
# If username does not match, then skip
if username != vals['username']:
print(f'WARNING! Username does not match. {username} != {vals["username"]}')
return
# If it has a flag ensure: absent, then remove user
if 'ensure' in vals and vals['ensure'] == 'absent':
action = 'remove'
# If expiry date is in the past, then remove user
if 'expiry' in vals:
activeDate = datetime.datetime.strptime(vals['expiry'], '%Y-%m-%d')
if activeDate < datetime.datetime.now():
action = 'remove'
if action == 'remove':
deleteUser(vals['username'])
if action == 'create':
createUser(vals['username'], vals['id'], vals['groups'])

def run():
"""Main run"""
if not os.path.isfile("/etc/usergroups/user-group"):
print("File /etc/usergroups/user-group not found")
return
with open("/etc/usergroups/user-group", "r", encoding='utf-8') as fd:
data = yaml.load(fd)
if "groups" in data:
for key, vals in data["groups"].items():
groupCheck(key, vals)
if "users" in data:
for key, vals in data["users"].items():
userCheck(key, vals)

if __name__ == "__main__":
run()
80 changes: 80 additions & 0 deletions base_image/config/opt/usergroups/user-group
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Each group should have these parameters defined:
# name - groupname
# gid - groupid (unique)
# Each user can have these parameters defined:
# username - username (mandatory)
# full_name - Full Name (mandatory)
# expiry - Expiry date (optional, default - none)
# email - Email (mandatory)
# id - This is used as UID and GID (mandatory, unique)
# dn - User's used DNs (optional, array, default - none). This will be added to grid-mapfile
# voms - User's voms role (optional, array, default - none). This wwill be added to voms-mapfile
# groups - Which groups user belongs (optional, array, default - same as his username)
# ================================================
groups:
gpuusers:
name: 'gpuusers'
gid: 4444
uerj:
name: 'uerj'
gid: 4999
docker:
name: 'docker'
gid: 5555
allcit:
name: 'allcit'
gid: 6666
sdntestbed:
name: 'sdntestbed'
gid: 7777
qnet:
name: 'qnet'
gid: 8888
btl:
name: 'btl'
gid: 9999

users:
jbalcas:
username: jbalcas
full_name: Justas Balcas
email: [email protected]
id: 3000
expiry: '2024-07-01'
dn:
- '/DC=ch/DC=cern/OU=Organic Units/OU=Users/CN=jbalcas/CN=751133/CN=Justas Balcas'
groups:
- allcit
- wheel
- cms
- gpuusers
- sdntestbed
- physsusy
- qnet
- tier2kube
- docker
cmsuser:
username: cmsuser
full_name: Default cmsuser account
email: [email protected]
id: 2009
voms:
- '/cms/*'
groups:
- allcit
- cms
glow:
username: glow
full_name: Default GLOW VO Pilot
email: [email protected]
ignore2fa: true
id: 2017
subscribe_to_mailings: False
shell: /sbin/nologin
managehome: false
voms:
- '/GLOW/chtc/*'
- '/GLOW/Role=htpc/*'
- '/GLOW/*'
groups:
- allcit
4 changes: 3 additions & 1 deletion xrootd/xcache-server/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
FROM opensciencegrid/software-base:23-al8-release
ARG RELEASE=latest
FROM cmscaltech/base_image:$RELEASE
# NOTES
# 2022 Mar 10th - Disable osg-upcoming, as it brings 5.x release with TLS.
# We are seeing a lot of TLS issue reading from Nebraska and Florida
# 2023 Dec 15th - Move to OSG 23 AlmaLinux 8 Release
# 2024 Feb 7th - Move to cmscaltech/base_image (which is based on OSG Image. See base_image repo)

ARG UNAME=xrootd
ARG UID=2010
Expand Down
5 changes: 4 additions & 1 deletion xrootd/xrootd-mon/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
FROM opensciencegrid/software-base:23-al8-release
ARG RELEASE=latest
FROM cmscaltech/base_image:$RELEASE
# NOTES
# 2024 Feb 7th - Move to cmscaltech/base_image (which is based on OSG Image. See base_image repo)

RUN yum -y install xrootd-client gfal2-util gfal2-all gfal2-python3 python3-gunicorn && yum clean all

Expand Down
5 changes: 4 additions & 1 deletion xrootd/xrootd-sense-cleaner/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
FROM opensciencegrid/software-base:23-al8-release
ARG RELEASE=latest
FROM cmscaltech/base_image:$RELEASE
# NOTES
# 2024 Feb 7th - Move to cmscaltech/base_image (which is based on OSG Image. See base_image repo)

ADD sense-cleaner.sh /etc/sense-cleaner.sh

Expand Down
5 changes: 4 additions & 1 deletion xrootd/xrootd-stageout-server/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
FROM opensciencegrid/software-base:23-al8-release
ARG RELEASE=latest
FROM cmscaltech/base_image:$RELEASE
# NOTES
# 2024 Feb 7th - Move to cmscaltech/base_image (which is based on OSG Image. See base_image repo)

ARG UNAME=xrootd
ARG UID=2010
Expand Down

0 comments on commit 1ccc187

Please sign in to comment.