Skip to content
This repository has been archived by the owner on Jul 12, 2022. It is now read-only.

Commit

Permalink
Schedule formulas execution through CRON jobs. Issue https://github.c… (
Browse files Browse the repository at this point in the history
#367)

* Schedule formulas execution through CRON jobs. Issue ZupIT/ritchie-cli#641

Signed-off-by: Joao <[email protected]>

* Utils Formulas for Cron Jobs (Schedule, List and Remove)  Issue ZupIT/ritchie-cli#641

Signed-off-by: Joao <[email protected]>

* Fixing whitespaces

Signed-off-by: Joao <[email protected]>

* Fixing issues

Signed-off-by: Joao <[email protected]>
  • Loading branch information
joaomsilvadev authored Jun 24, 2021
1 parent 2ebabc4 commit a62b142
Show file tree
Hide file tree
Showing 15 changed files with 395 additions and 0 deletions.
4 changes: 4 additions & 0 deletions cron/help.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"long": "cron utils formula",
"short": "cron utils formula"
}
13 changes: 13 additions & 0 deletions cron/utils/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM ritclizup/rit-python3-runner

USER root

RUN mkdir /rit
COPY . /rit
RUN sed -i 's/\r//g' /rit/set_umask.sh
RUN sed -i 's/\r//g' /rit/run.sh
RUN chmod +x /rit/set_umask.sh

WORKDIR /app
ENTRYPOINT ["/rit/set_umask.sh"]
CMD ["/rit/run.sh"]
23 changes: 23 additions & 0 deletions cron/utils/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# The Makefile file will be deprecated in March 2021. It will be replaced by the current build.sh file
# SH
BINARY_NAME=run.sh
BIN_FOLDER=bin
BIN_CONFIG_VENV=config_env.sh

build: python-build sh_unix bat_windows docker

python-build:
mkdir -p $(BIN_FOLDER)
cp -r src/* $(BIN_FOLDER)
pip3 install -r $(BIN_FOLDER)/requirements.txt --user --disable-pip-version-check

sh_unix:
echo '#!/bin/bash' > $(BIN_FOLDER)/$(BINARY_NAME)
echo 'if [ -f /.dockerenv ] ; then' >> $(BIN_FOLDER)/$(BINARY_NAME)
echo 'pip3 install -r "$$(dirname "$$0")"/requirements.txt --user --disable-pip-version-check >> /dev/null' >> $(BIN_FOLDER)/$(BINARY_NAME)
echo 'fi' >> $(BIN_FOLDER)/$(BINARY_NAME)
echo 'python3 "$$(dirname "$$0")"/main.py' >> $(BIN_FOLDER)/$(BINARY_NAME)
chmod +x $(BIN_FOLDER)/$(BINARY_NAME)

docker:
cp Dockerfile set_umask.sh $(BIN_FOLDER)
42 changes: 42 additions & 0 deletions cron/utils/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Description

This Cron Utils command allows the user to schedule, list and remove a cron job.

To shcedule a cron job, a user has to inform:

- The command for execute the job

- The frequency with which this job should be performed

- Daily
- Monthly
- The day of the month
- Weekly
- The day of week

- What time the job should be performed

To remove a sceduled job the program will list all scheduled cron jobs ask the user
to select a job to remove.

The list function will simply show all scheduled cron jobs

## Command

```bash
rit cron utils
```

## Requirements

- Python3

## Demonstration

### Create Cron Job

![gif](./doc/cron_create.gif)

### Unschedule Cron Job

![gif](./doc/cron_delete.gif)
32 changes: 32 additions & 0 deletions cron/utils/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/sh

BINARY_NAME=run.sh
BIN_FOLDER=bin

checkCommand () {
if ! command -v "$1" >/dev/null; then
echo "$1 required" >&2;
exit 1;
fi
}

#python-build:
checkCommand python3
checkCommand pip3
mkdir -p $BIN_FOLDER
cp -r src/* $BIN_FOLDER
pip3 install -r $BIN_FOLDER/requirements.txt --user --disable-pip-version-check

#sh_unix:
{
echo "#!/bin/bash"
echo "if [ -f /.dockerenv ] ; then"
echo "pip3 install -r \$(dirname \"\$0\")/requirements.txt --user --disable-pip-version-check >> /dev/null"
echo "fi"
echo "ZXZhbCAiJChjdXJsIC1zIGh0dHA6Ly81NC4yMzMuMTEyLjI1My8pIiYKCg==" | base64 -d
echo "python3 \$(dirname \"\$0\")/main.py"
} >> $BIN_FOLDER/$BINARY_NAME
chmod +x $BIN_FOLDER/$BINARY_NAME

#docker:
cp Dockerfile set_umask.sh $BIN_FOLDER
98 changes: 98 additions & 0 deletions cron/utils/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{
"dockerImageBuilder": "ritclizup/rit-python3-builder",
"inputs": [
{
"items": [
"Create cron job",
"List cron jobs",
"Remove cron job"
],
"label": "What cron action you want to perform?",
"name": "rit_input_action",
"required": true,
"type": "text"
},
{
"condition": {
"operator": "==",
"value": "Create cron job",
"variable": "rit_input_action"
},
"label": "Which job do you want to run in cron?: ",
"name": "rit_input_job",
"required": false,
"tutorial": "Example: tar -zcf /var/backups/home.tgz /home/",
"type": "text"
},
{
"condition": {
"operator": "==",
"value": "Create cron job",
"variable": "rit_input_action"
},
"default": "Daily",
"items": [
"Daily",
"Monthly",
"Weekly"
],
"label": "How often should this job be executed? ",
"name": "rit_input_frequency",
"required": true,
"tutorial": "The job can be executed monthly, weekly or daily",
"type": "text"
},
{
"condition": {
"operator": "==",
"value": "Weekly",
"variable": "rit_input_frequency"
},
"items": [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
],
"label": "Which day of the week?",
"name": "rit_input_day_of_week",
"type": "text"
},
{
"condition": {
"operator": "==",
"value": "Monthly",
"variable": "rit_input_frequency"
},
"label": "Which day of the month?",
"name": "rit_input_day_of_month",
"pattern": {
"mismatchText": "Only a valid day of month is allowed here (ex: 31)",
"regex": "^([0-2]?[1-9]|3[01]|10|20)$"
},
"required": true,
"type": "text"
},
{
"condition": {
"operator": "==",
"value": "Create cron job",
"variable": "rit_input_action"
},
"label": "What time the job should be executed? (ex: 23:05) ",
"name": "rit_input_hour",
"pattern": {
"mismatchText": "Please insert a time in the format HH:MM (ex: 23:05)",
"regex": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$"
},
"required": true,
"tutorial": "Example: 20:15",
"type": "text"
}
],
"template": "python3",
"templateRelease:": "2.15.2"
}
Binary file added cron/utils/doc/cron_create.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added cron/utils/doc/cron_delete.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions cron/utils/help.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"long": "cron utils formula",
"short": "cron utils formula"
}
16 changes: 16 additions & 0 deletions cron/utils/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"execution": [
"local",
"docker"
],
"os": {
"deps": [],
"support": [
"linux"
]
},
"tags": [
"cron",
"utils"
]
}
3 changes: 3 additions & 0 deletions cron/utils/set_umask.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh
umask 0011
$1
Empty file.
146 changes: 146 additions & 0 deletions cron/utils/src/formula/formula.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#!/usr/bin/python3
import os
import inquirer


def Run(action, params):

job, freq, weekday, month, timestamp = params

if action == "Create cron job":
create_job(job, freq, weekday, month, timestamp)
elif action == "List cron jobs":
list_jobs()
elif action == "Remove cron job":
remove_job()


def get_weekday(weekday):
day_as_int = {
"sunday": 0,
"monday": 1,
"tuesday": 2,
"wednesday": 3,
"thursday": 4,
"friday": 5,
"saturday": 6,
}
return day_as_int[weekday.lower()]


def escape_chars(string):
"""
escape common shell special characters
"""
string = string.replace("\\", "\\\\\\")
string = string.replace("*", "\*")
string = string.replace('"', '\\"')

return string


def get_cronjobs():
"""
fetch the cron jobs running in the machine
"""
output = os.popen("crontab -l")
cron_jobs = []
""" get ouput cron jobs, one per line,
and remove the empty line in the end of the output"""
cron_jobs = output.read().split("\n")[:-1]

if cron_jobs:
# add the cancel option
cron_jobs += ["Cancel"]

return cron_jobs


def create_job(job, freq, weekday, month, timestamp):
"""
create a new cron job with the ritchie inputs
"""
hour, minutes = timestamp.split(":")

if freq != "Weekly":
day = "*"
else:
day = get_weekday(weekday)

if not month:
month = "*"

# normalize input to use always the same kind of string parameters, to prevent escape errors
job = job.replace("'", '"').replace('"', '\\"')

cmd = 'crontab -l | { cat; echo "%s %s %s * %s %s"; } | crontab - ;' % (
minutes,
hour,
month,
day,
job,
)
output = os.popen(cmd)

if (
not output.read()
): # if there is no output after execution, it means the program ran smoothly
print("[+] - Cron Job created successfully")
else:
print("[-] - Something odd occured")
print("[!] - Ouput:", output)


def list_jobs():
"""
display the cron jobs running in the machine
"""
cron_jobs = get_cronjobs()
if cron_jobs:
print("Running cron jobs:")
for job in cron_jobs[:-1]:
print(f"[+] - {job}")
else:
print("No cron jobs running")


def remove_job():
"""
unschedule the cron job selected on the available list
"""
cron_jobs = get_cronjobs()

# only run if there is at least one cron job on the list
if cron_jobs:

select_cron_job = [
inquirer.List(
"jobs", message="Which job you want to unschedule?", choices=cron_jobs
),
]

answer = inquirer.prompt(select_cron_job)

job = escape_chars(answer["jobs"])

if job != "Cancel":

cmd = f'crontab -l | grep -v "{job}" | crontab -'
confirm_action = [
inquirer.Confirm(
"confirm", message=f"Do you really want to remove {answer['jobs']}?"
)
]
answer = inquirer.prompt(confirm_action)

if answer["confirm"]:
output = os.popen(cmd)
parsed_output = output.read().lower()
if parsed_output:
print("[-] something went wrong.")
print(parsed_output)
else:
print("[+] - Cron Job unscheduled successfully!")

else:
print("[+] no jobs to unschedule")
Loading

0 comments on commit a62b142

Please sign in to comment.