Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustavo Carneiro committed Jul 17, 2017
0 parents commit d1aa082
Show file tree
Hide file tree
Showing 18 changed files with 732 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# http://editorconfig.org

root = true

[*]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8
end_of_line = lf


[LICENSE]
insert_final_newline = false
15 changes: 15 additions & 0 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
* Yet Another Cron version:
* Python version:
* Operating System:

### Description

Describe what you were trying to get done.
Tell us what happened, what went wrong, and what you expected to happen.

### What I Did

```
Paste the command(s) you ran and the output.
If there was a crash, please include the traceback here.
```
62 changes: 62 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# pyenv python configuration file
.python-version
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

MIT License

Copyright (c) 2017, Gambit Research

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 changes: 7 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
include LICENSE
include README.rst

recursive-include tests *
recursive-include example *
recursive-exclude * __pycache__
recursive-exclude * *.py[co]
19 changes: 19 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
================
Yet Another Cron
================


A modern Cron replacement that is Docker-friendly


* Free software: MIT license


Features
--------

* "Crontab" is in YAML format
* Builtin sending of Sentry and Mail outputs
* Flexible configation: you decide how to determine of a cron job failed or not
* Logs everything to stdout/stderr, making it suitable to run inside Docker,
Kubernetes, or 12 factor environments.
43 changes: 43 additions & 0 deletions example/adhoc.ycron.d/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

defaults:
shell: /bin/bash

concurrencyPolicy: Allow
# Allow (default): allows concurrently running jobs
# Forbid: forbids concurrent runs, skipping next run if previous hasn’t finished yet
# Replace: cancels currently running job and replaces it with a new one

failsWhen:
producesStdout: false
producesStderr: true
nonzeroReturn: true

onFailure:
report:
sentry:
# dsn:
# value: example
mail:
from: [email protected]
to: [email protected]
smtp_host: 127.0.0.1
smtp_port: 10025

jobs:
- name: test-01
command:
- echo
- "foobar"
schedule: "* * * * *"
captureStdout: true
failsWhen:
producesStdout: true

- name: test-02
command: |
echo "hello" 1>&2
sleep 1
echo "world"
exit 10
schedule: "* * * * *"
captureStderr: true
9 changes: 9 additions & 0 deletions requirements_dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pip==8.1.2
bumpversion==0.5.3
wheel==0.29.0
watchdog==0.8.3
flake8==2.6.0
tox==2.3.1
coverage==4.1


8 changes: 8 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[bdist_wheel]
universal = 1

[flake8]
exclude = docs

[aliases]
# Define setup.py command aliases here
54 changes: 54 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""The setup script."""

from setuptools import setup, find_packages

with open('README.rst') as readme_file:
readme = readme_file.read()


requirements = [
"PyYAML",
"crontab",
"aiohttp",
"raven",
"raven-aiohttp",
"aiosmtplib",
]


setup_requirements = [
'setuptools_scm',
]

test_requirements = [
'pytest',
]

setup(
name='yacron',
version='0.1.0',
description="A modern Cron replacement that is Docker-friendly",
long_description=readme,
author="Gustavo Carneiro",
author_email='[email protected]',
url='https://github.com/gjcarneiro/yacron',
packages=find_packages(include=['yacron']),
include_package_data=True,
install_requires=requirements,
license="MIT license",
zip_safe=False,
keywords='yacron',
classifiers=[
'Development Status :: 2 - Pre-Alpha',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
],
setup_requires=setup_requirements,
use_scm_version=True,
)
Empty file added tests/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from yacron import config


def test_mergedicts():
assert config.mergedicts({"a", 1,}, {"b": 2}) == {"a": 1, "b": 2}
22 changes: 22 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[tox]
envlist = py35, flake8

[travis]
python =
3.5: py35

[testenv:flake8]
basepython=python
deps=flake8
commands=flake8 yacron

[testenv]
setenv =
PYTHONPATH = {toxinidir}

commands = python setup.py test

; If you want to make tox run the tests with the same versions, create a
; requirements.txt with the pinned versions and uncomment the following lines:
; deps =
; -r{toxinidir}/requirements.txt
Empty file added yacron/__init__.py
Empty file.
38 changes: 38 additions & 0 deletions yacron/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import sys
import logging
import argparse
import signal
import asyncio
import asyncio.subprocess

from yacron.cron import Cron


def main():
parser = argparse.ArgumentParser()
parser.add_argument('-c', "--config", default="/etc/ycron.d",
metavar="DIR")
parser.add_argument('-l', "--log-level", default="INFO")
args = parser.parse_args()

logging.basicConfig(level=getattr(logging, args.log_level))
# logging.getLogger("asyncio").setLevel(logging.WARNING)

cron = Cron(args.config)

if sys.platform == "win32":
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
else:
loop = asyncio.get_event_loop()

loop.add_signal_handler(signal.SIGINT, cron.signal_shutdown)
loop.add_signal_handler(signal.SIGTERM, cron.signal_shutdown)
try:
loop.run_until_complete(cron.run())
finally:
loop.close()


if __name__ == '__main__':
main()
Loading

0 comments on commit d1aa082

Please sign in to comment.