Introduction
GitLab Issue Templates allow teams to standardize and automate issue creation, ensuring that all necessary information is collected upfront and that processes are consistently followed. Automating issue creation using these templates can lead to better collaboration, streamlined workflows, and faster resolution of issues.
1) Kubernetes Pod Restart
2) Kubernetes Deployment Image Patch
What Are GitLab Issue Templates?
GitLab issue templates are pre-defined formats for issues that provide a structured way to report bugs, suggest features, or handle tasks. They help ensure that team members include all relevant information when creating issues, reducing miscommunication and the need for follow-up.
Why Use GitLab Issue Templates?
Consistency: Ensure that all issues follow a uniform structure.
Speed: Quickly generate issues by filling in pre-set fields.
Clarity: Include necessary details, such as steps to reproduce bugs, acceptance criteria, and links to relevant documentation.
Automation: Automate the issue creation process by embedding workflows into the template.
Automating Template to Restart Kubernetes Pod and Patch Deployment
Setting Up a Template in Your Repository
Issue templates are stored in your repository and can be reused across multiple issues. To create a template, follow these steps:
Navigate to your GitLab repository.
Go to the *.gitlab** or issue_templates folder in the root directory. If the folder doesn't exist, create one and add a new Markdown file (.md) for each issue template. For example, you can name it*
k8s_deployment_patch.md
### Environment
environment=
### Namespace
namespace=
### Deployment Name
deployment=
### Container Name
container_name=
### Image Name
image=
### Justification
/label ~"type::issue" ~"action::deployment-patch"
k8s_deployments_restart.md
### Environment
environment=
### Namespace
namespace=
### Deployment Name
deployment=
### Justification
/label ~"type::issue" ~"action::pod-restart"
Merge the Code And Verify
Project --> Issues --> Create New Issue
Lets Create Automation Code(Using Python)
1) Code To List Created Issue
import gitlab
import re
import os
import subprocess
from common import check_namespace_exists, check_deployment_exists, close_issue, approval_verify,extract_info,approver_list
def init_gitlab_connection(private_token):
return gitlab.Gitlab('https://gitlab.com', private_token=private_token)
def process_issues(issues, project):
for issue in issues:
labels = set(issue.labels)
comment = (f" 🤖 Its a automated genetated note. Waiting for approval from @{', '.join(approver_list)}")
notes = issue.notes.list(get_all=True)
if not notes:
issue.notes.create({'body': comment})
if 'action::pod-restart' in labels:
namespace, deployment, env, img, cn = extract_info(issue.description)
if approval_verify(issue):
result = subprocess.run(['python', 'deployment_restart.py', namespace, deployment, env], capture_output=True, text=True)
res = result.returncode
if res == 0:
comment = (f"Deployment '{deployment}' in Namespace '{namespace}' has been restarted 🚀")
else:
comment = (f"Deployment '{deployment}' or Namespace '{namespace}' not found 😔")
close_issue(issue,comment,res)
elif 'action::deployment-patch' in labels:
namespace, deployment, env, img, cn = extract_info(issue.description)
if approval_verify(issue):
result = subprocess.run(['python', 'deployment_patch.py', namespace, deployment, env, img, cn], capture_output=True, text=True)
res = result.returncode
if res == 0:
comment = (f"Deployment '{deployment}' in Namespace '{namespace}' Patched sucessfully with {img} 🚀")
else:
comment = (f"Deployment '{deployment}' or Namespace '{namespace}' not found 😔")
close_issue(issue,comment,res)
def main():
private_token = os.getenv('gitlab_token')
gitlab_project = os.getenv('gitlab_project')
gl = init_gitlab_connection(private_token)
project = gl.projects.get(gitlab_project)
issues = project.issues.list(state='opened')
if not issues:
print("No issues found.")
else:
process_issues(issues, project)
if __name__ == '__main__':
main()
2) Code for Common work
from kubernetes import client, config
import argparse
import datetime
import sys
import re
approver_list = ['champ25']
config.load_kube_config()
def close_issue(issue,comment,res):
notes = issue.notes.list(get_all=True)
issue.notes.create({'body': comment})
if res == 0:
issue.state_event = 'close'
issue.save()
def approval_verify(issue):
notes = issue.notes.list(get_all=True)
for note in notes:
if 'approved' in note.body.lower() and note.author['username'] in approver_list:
new_comment = f"🤖 Approval has been noted by @{note.author.get('username')}.🤖"
issue.notes.create({'body': new_comment})
return True
return False
def extract_info(description):
namespace_pattern = re.compile(r'namespace=\s*(\S+)')
deployment_pattern = re.compile(r'deployment=\s*(\S+)')
env_pattern = re.compile(r'environment=\s*(\S+)')
cn_pattern = re.compile(r'container_name=\s*(\S+)')
img_pattern = re.compile(r'image=\s*(\S+)')
namespace_match = namespace_pattern.search(description)
deployment_match = deployment_pattern.search(description)
env_match = env_pattern.search(description)
cn_match = cn_pattern.search(description)
img_match = img_pattern.search(description)
namespace = namespace_match.group(1) if namespace_match else None
deployment = deployment_match.group(1) if deployment_match else None
env = env_match.group(1) if env_match else None
cn = cn_match.group(1) if cn_match else None
img = img_match.group(1) if img_match else None
return namespace, deployment, env, img, cn
def check_namespace_exists(namespace_name):
print(namespace_name)
v1 = client.CoreV1Api()
try:
v1.read_namespace(name=namespace_name)
return True
except client.exceptions.ApiException as e:
if e.status == 404:
print(f"Namespace '{namespace_name}' does not exist.")
sys.exit(1)
else:
print(f"Error occurred: {e}")
sys.exit(1)
return False
def check_deployment_exists(deployment_name, namespace_name):
apps_v1 = client.AppsV1Api()
try:
apps_v1.read_namespaced_deployment(name=deployment_name, namespace=namespace_name)
return True
except client.exceptions.ApiException as e:
if e.status == 404:
print(f"Deployment '{deployment_name}' does not exist in namespace '{namespace_name}'.")
sys.exit(1)
else:
print(f"Error occurred: {e}")
sys.exit(1)
return False
3) Code for Restarting Pods
from kubernetes import client, config
import argparse
import datetime
import sys
from common import check_namespace_exists, check_deployment_exists, close_issue, approval_verify,extract_info
def restart_deployment(namespace, deployment_name, env):
if check_namespace_exists(namespace):
if check_deployment_exists(deployment_name, namespace):
api_instance = client.AppsV1Api()
try:
patch = {
"spec": {
"template": {
"metadata": {
"annotations": {
"kubectl.kubernetes.io/restartedAt": datetime.datetime.utcnow().isoformat()
}
}
}
}
}
# Apply the updated deployment
api_instance.patch_namespaced_deployment(deployment_name, namespace, body=patch)
except client.exceptions.ApiException as e:
print(f"Exception when calling AppsV1Api->patch_namespaced_deployment: {e}")
def main():
# Define the namespace and deployment name
config.load_kube_config()
parser = argparse.ArgumentParser()
parser.add_argument('namespace', type=str, help='Namespace of the deployment')
parser.add_argument('deployment', type=str, help='Name of the deployment')
parser.add_argument('env', type=str, help='Cluster Environment')
args = parser.parse_args()
# Restart the deployment
comment = restart_deployment(args.namespace, args.deployment, args.env)
if __name__ == '__main__':
main()
4) Create Code for Patching the Deployment
from kubernetes import client, config
import argparse
import datetime
import sys
from common import check_namespace_exists, check_deployment_exists, close_issue, approval_verify,extract_info
def patch_deployment(namespace, deployment_name, env, img, cn):
if check_namespace_exists(namespace):
if check_deployment_exists(deployment_name, namespace):
print("Validation Sucessfull")
api_instance = client.AppsV1Api()
try:
patch = {
"spec": {
"template": {
"spec": {
"containers": [
{
"name": cn,
"image": img
}
]
}
}
}
}
# Apply the updated deployment
api_instance.patch_namespaced_deployment(deployment_name, namespace, body=patch)
except client.exceptions.ApiException as e:
print(f"Exception when calling AppsV1Api->patch_namespaced_deployment: {e}")
def main():
# Define the namespace and deployment name
config.load_kube_config()
parser = argparse.ArgumentParser()
parser.add_argument('namespace',help='Namespace of the deployment')
parser.add_argument('deployment', help='Name of the deployment')
parser.add_argument('env', help='Cluster Environment')
parser.add_argument('img', help='Image to be patched')
parser.add_argument('cn', help='Container Name to be patched')
args = parser.parse_args()
# Patch the deployment
patch_deployment(args.namespace, args.deployment, args.env, args.img, args.cn)
if __name__ == '__main__':
main()
6) Create Image to Use the above Code
# Use the official Python base image
FROM python:3.9-slim
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
KUBECONFIG=/src/.kube/config
# Create necessary directories
RUN mkdir -p /src/.kube
# Set the working directory
WORKDIR /src
# Copy Kubernetes config and requirements
COPY config /src/.kube/
COPY requirments.txt /src/
# Debug step: List files to ensure `requirements.txt` is copied
RUN ls -l /src/
# Install Python dependencies
RUN pip install --upgrade pip && \
pip install --no-cache-dir -r /src/requirments.txt || \
(echo "Error occurred during pip install" && exit 1)
# Install Kubernetes client (if not already in requirements.txt)
RUN pip install --no-cache-dir kubernetes
requirments.txt file
kubernetes
python-gitlab
requests
Create Image and push it to your Repo.
Create Gitlab-ci.yaml file
######################## Default image #######################
default:
image: omvedi25/devops-tool:v1.1
############################# Stages ######################################
stages:
- devops-automation
########################### Templates ######################################
devops-automation:
stage: devops-automation
script:
- cd src
- python issuelist.py
Now Lets See the Working
Create a new issue to restart the pod
Move to Pipeline and run it
Go to Issue and Verify
Waiting got the approval for the valid requester
Add **Approved* in Comment login to valid user*
Verify the Pods Status
Lets Patch the Deployment
Verify the Existing Image assigned to Deployment
Trigger the Pipeline
Run the Pipeline again and verify issue
Note
We can create a scheduler to run the pipeline every 5 min
Conclusion
GitLab Issue Templates are a powerful tool for standardizing and automating issue creation across your team. By incorporating these templates into your workflow and integrating them with automation tools like GitLab CI/CD or monitoring systems, you can improve consistency, save time, and ensure critical issues are addressed promptly.