Showing preview only (2,670K chars total). Download the full file or copy to clipboard to get everything.
Repository: Yelp/Tron
Branch: master
Commit: 5779faaa0153
Files: 347
Total size: 2.5 MB
Directory structure:
gitextract_3urb6sob/
├── .dockerignore
├── .github/
│ └── workflows/
│ ├── ci.yml
│ └── security-review.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .pyautotest
├── .readthedocs.yaml
├── AGENTS.md
├── CODEOWNERS
├── LICENSE.txt
├── MANIFEST.in
├── Makefile
├── OWNERS
├── README.md
├── bin/
│ ├── generate_tron_tab_completion_cache
│ ├── tronctl
│ ├── tronctl_tabcomplete.sh
│ ├── trond
│ ├── tronfig
│ ├── tronrepl
│ ├── tronview
│ └── tronview_tabcomplete.sh
├── contrib/
│ ├── migration_script.py
│ ├── mock_patch_checker.py
│ ├── namespace_cleanup.sh
│ ├── patch-config-loggers.diff
│ ├── sync-from-yelp-prod.sh
│ └── sync_namespaces_jobs.py
├── debian/
│ ├── changelog
│ ├── compat
│ ├── control
│ ├── copyright
│ ├── docs
│ ├── install
│ ├── pycompat
│ ├── pyversions
│ ├── rules
│ ├── tron.conffiles
│ ├── tron.default
│ ├── tron.dirs
│ ├── tron.example
│ ├── tron.links
│ ├── tron.manpages
│ ├── tron.postinst
│ ├── tron.service
│ ├── tron.upstart
│ └── watch
├── dev/
│ ├── config/
│ │ ├── MASTER.yaml
│ │ └── _manifest.yaml
│ └── logging.conf
├── docs/
│ └── source/
│ ├── _static/
│ │ └── nature.css
│ ├── command_context.rst
│ ├── conf.py
│ ├── config.rst
│ ├── developing.rst
│ ├── generated/
│ │ ├── modules.rst
│ │ ├── tron.actioncommand.rst
│ │ ├── tron.api.adapter.rst
│ │ ├── tron.api.async_resource.rst
│ │ ├── tron.api.auth.rst
│ │ ├── tron.api.controller.rst
│ │ ├── tron.api.requestargs.rst
│ │ ├── tron.api.resource.rst
│ │ ├── tron.api.rst
│ │ ├── tron.command_context.rst
│ │ ├── tron.commands.authentication.rst
│ │ ├── tron.commands.backfill.rst
│ │ ├── tron.commands.client.rst
│ │ ├── tron.commands.cmd_utils.rst
│ │ ├── tron.commands.display.rst
│ │ ├── tron.commands.retry.rst
│ │ ├── tron.commands.rst
│ │ ├── tron.config.config_parse.rst
│ │ ├── tron.config.config_utils.rst
│ │ ├── tron.config.manager.rst
│ │ ├── tron.config.rst
│ │ ├── tron.config.schedule_parse.rst
│ │ ├── tron.config.schema.rst
│ │ ├── tron.config.static_config.rst
│ │ ├── tron.core.action.rst
│ │ ├── tron.core.actiongraph.rst
│ │ ├── tron.core.actionrun.rst
│ │ ├── tron.core.job.rst
│ │ ├── tron.core.job_collection.rst
│ │ ├── tron.core.job_scheduler.rst
│ │ ├── tron.core.jobgraph.rst
│ │ ├── tron.core.jobrun.rst
│ │ ├── tron.core.recovery.rst
│ │ ├── tron.core.rst
│ │ ├── tron.eventbus.rst
│ │ ├── tron.kubernetes.rst
│ │ ├── tron.manhole.rst
│ │ ├── tron.mcp.rst
│ │ ├── tron.mesos.rst
│ │ ├── tron.metrics.rst
│ │ ├── tron.node.rst
│ │ ├── tron.prom_metrics.rst
│ │ ├── tron.rst
│ │ ├── tron.scheduler.rst
│ │ ├── tron.serialize.filehandler.rst
│ │ ├── tron.serialize.rst
│ │ ├── tron.serialize.runstate.dynamodb_state_store.rst
│ │ ├── tron.serialize.runstate.rst
│ │ ├── tron.serialize.runstate.shelvestore.rst
│ │ ├── tron.serialize.runstate.statemanager.rst
│ │ ├── tron.serialize.runstate.yamlstore.rst
│ │ ├── tron.ssh.rst
│ │ ├── tron.trondaemon.rst
│ │ ├── tron.utils.collections.rst
│ │ ├── tron.utils.crontab.rst
│ │ ├── tron.utils.exitcode.rst
│ │ ├── tron.utils.logreader.rst
│ │ ├── tron.utils.observer.rst
│ │ ├── tron.utils.persistable.rst
│ │ ├── tron.utils.proxy.rst
│ │ ├── tron.utils.queue.rst
│ │ ├── tron.utils.rst
│ │ ├── tron.utils.state.rst
│ │ ├── tron.utils.timeutils.rst
│ │ ├── tron.utils.trontimespec.rst
│ │ ├── tron.utils.twistedutils.rst
│ │ └── tron.yaml.rst
│ ├── index.rst
│ ├── jobs.rst
│ ├── man/
│ │ ├── tronctl.1
│ │ ├── trond.8
│ │ ├── tronfig.1
│ │ └── tronview.1
│ ├── man_tronctl.rst
│ ├── man_trond.rst
│ ├── man_tronfig.rst
│ ├── man_tronview.rst
│ ├── overview.rst
│ ├── sample_config.yaml
│ ├── tools.rst
│ ├── tron.yaml
│ ├── tronweb.rst
│ ├── tutorial.rst
│ └── whats-new.rst
├── itest.sh
├── mypy.ini
├── osx-bdb.sh
├── package.json
├── pyproject.toml
├── requirements-dev-minimal.txt
├── requirements-dev.txt
├── requirements-docs.txt
├── requirements-minimal.txt
├── requirements.txt
├── setup.cfg
├── setup.py
├── testfiles/
│ └── MASTER.yaml
├── testifycompat/
│ ├── __init__.py
│ ├── assertions.py
│ ├── bin/
│ │ ├── __init__.py
│ │ └── migrate.py
│ └── fixtures.py
├── tests/
│ ├── __init__.py
│ ├── actioncommand_test.py
│ ├── api/
│ │ ├── __init__.py
│ │ ├── adapter_test.py
│ │ ├── auth_test.py
│ │ ├── controller_test.py
│ │ ├── requestargs_test.py
│ │ └── resource_test.py
│ ├── assertions.py
│ ├── bin/
│ │ ├── __init__.py
│ │ ├── action_runner_test.py
│ │ ├── action_status_test.py
│ │ ├── check_tron_jobs_test.py
│ │ ├── get_tron_metrics_test.py
│ │ └── recover_batch_test.py
│ ├── command_context_test.py
│ ├── commands/
│ │ ├── __init__.py
│ │ ├── backfill_test.py
│ │ ├── client_test.py
│ │ ├── cmd_utils_test.py
│ │ ├── display_test.py
│ │ └── retry_test.py
│ ├── config/
│ │ ├── __init__.py
│ │ ├── config_parse_test.py
│ │ ├── config_utils_test.py
│ │ ├── manager_test.py
│ │ └── schedule_parse_test.py
│ ├── core/
│ │ ├── __init__.py
│ │ ├── action_test.py
│ │ ├── actiongraph_test.py
│ │ ├── actionrun_test.py
│ │ ├── job_collection_test.py
│ │ ├── job_scheduler_test.py
│ │ ├── job_test.py
│ │ ├── jobgraph_test.py
│ │ ├── jobrun_test.py
│ │ └── recovery_test.py
│ ├── data/
│ │ ├── logging.conf
│ │ └── test_config.yaml
│ ├── eventbus_test.py
│ ├── kubernetes_test.py
│ ├── mcp_reconfigure_test.py
│ ├── mcp_test.py
│ ├── mesos_test.py
│ ├── metrics_test.py
│ ├── mocks.py
│ ├── node_test.py
│ ├── sandbox.py
│ ├── scheduler_test.py
│ ├── serialize/
│ │ ├── __init__.py
│ │ ├── filehandler_test.py
│ │ └── runstate/
│ │ ├── __init__.py
│ │ ├── dynamodb_state_store_test.py
│ │ ├── shelvestore_test.py
│ │ ├── statemanager_test.py
│ │ └── yamlstore_test.py
│ ├── ssh_test.py
│ ├── test_id_rsa
│ ├── test_id_rsa.pub
│ ├── testingutils.py
│ ├── tools/
│ │ └── sync_tron_state_from_k8s_test.py
│ ├── trond_test.py
│ ├── trondaemon_test.py
│ └── utils/
│ ├── __init__.py
│ ├── collections_test.py
│ ├── crontab_test.py
│ ├── logreader_test.py
│ ├── observer_test.py
│ ├── proxy_test.py
│ ├── shortOutputTest.txt
│ ├── state_test.py
│ ├── timeutils_test.py
│ └── trontimespec_test.py
├── tools/
│ ├── action_dag_diagram.py
│ ├── compress_json.py
│ ├── inspect_serialized_state.py
│ ├── migration/
│ │ ├── migrate_config_0.2_to_0.3.py
│ │ ├── migrate_config_0.5.1_to_0.5.2.py
│ │ ├── migrate_state.py
│ │ └── migrate_state_1.3.15_to_1.4.0.py
│ ├── pickles_to_json.py
│ └── sync_tron_state_from_k8s.py
├── tox.ini
├── tron/
│ ├── __init__.py
│ ├── actioncommand.py
│ ├── api/
│ │ ├── __init__.py
│ │ ├── adapter.py
│ │ ├── async_resource.py
│ │ ├── auth.py
│ │ ├── controller.py
│ │ ├── requestargs.py
│ │ └── resource.py
│ ├── bin/
│ │ ├── action_runner.py
│ │ ├── action_status.py
│ │ ├── check_tron_datastore_staleness.py
│ │ ├── check_tron_jobs.py
│ │ ├── get_tron_metrics.py
│ │ └── recover_batch.py
│ ├── command_context.py
│ ├── commands/
│ │ ├── __init__.py
│ │ ├── authentication.py
│ │ ├── backfill.py
│ │ ├── client.py
│ │ ├── cmd_utils.py
│ │ ├── display.py
│ │ └── retry.py
│ ├── config/
│ │ ├── __init__.py
│ │ ├── config_parse.py
│ │ ├── config_utils.py
│ │ ├── manager.py
│ │ ├── schedule_parse.py
│ │ ├── schema.py
│ │ ├── static_config.py
│ │ └── tronfig_schema.json
│ ├── core/
│ │ ├── __init__.py
│ │ ├── action.py
│ │ ├── actiongraph.py
│ │ ├── actionrun.py
│ │ ├── job.py
│ │ ├── job_collection.py
│ │ ├── job_scheduler.py
│ │ ├── jobgraph.py
│ │ ├── jobrun.py
│ │ └── recovery.py
│ ├── default_config.yaml
│ ├── eventbus.py
│ ├── kubernetes.py
│ ├── logging.conf
│ ├── manhole.py
│ ├── mcp.py
│ ├── mesos.py
│ ├── metrics.py
│ ├── node.py
│ ├── prom_metrics.py
│ ├── scheduler.py
│ ├── serialize/
│ │ ├── __init__.py
│ │ ├── filehandler.py
│ │ └── runstate/
│ │ ├── __init__.py
│ │ ├── dynamodb_state_store.py
│ │ ├── shelvestore.py
│ │ ├── statemanager.py
│ │ └── yamlstore.py
│ ├── ssh.py
│ ├── trondaemon.py
│ ├── utils/
│ │ ├── __init__.py
│ │ ├── collections.py
│ │ ├── crontab.py
│ │ ├── exitcode.py
│ │ ├── logreader.py
│ │ ├── observer.py
│ │ ├── persistable.py
│ │ ├── proxy.py
│ │ ├── queue.py
│ │ ├── state.py
│ │ ├── timeutils.py
│ │ ├── trontimespec.py
│ │ └── twistedutils.py
│ └── yaml.py
├── tronweb/
│ ├── coffee/
│ │ ├── actionrun.coffee
│ │ ├── config.coffee
│ │ ├── dashboard.coffee
│ │ ├── graph.coffee
│ │ ├── job.coffee
│ │ ├── models.coffee
│ │ ├── navbar.coffee
│ │ ├── nodes.coffee
│ │ ├── routes.coffee
│ │ ├── timeline.coffee
│ │ └── views.coffee
│ ├── css/
│ │ ├── codemirror.css
│ │ ├── tronweb.less
│ │ └── whhg.css
│ ├── fonts/
│ │ └── SIL OFL Font License WebHostingHub Glyphs.txt
│ ├── index.html
│ └── js/
│ ├── backbone-min.js
│ ├── codemirror.js
│ ├── plugins.js
│ ├── underscore-min.js
│ ├── underscore.extra.js
│ ├── underscore.string.js
│ └── yaml.js
├── tronweb_tests/
│ ├── SpecRunner.html
│ ├── spec/
│ │ └── README
│ └── tests/
│ ├── actionrun_test.coffee
│ ├── dashboard_test.coffee
│ ├── navbar_test.coffee
│ ├── routes_test.coffee
│ └── timeline_test.coffee
└── yelp_package/
├── extra_requirements_yelp.txt
└── jammy/
└── Dockerfile
================================================
FILE CONTENTS
================================================
================================================
FILE: .dockerignore
================================================
.tox
.git
.idea
================================================
FILE: .github/workflows/ci.yml
================================================
---
name: tron-ci
on:
push:
branches:
- master
tags:
- v*.*
pull_request:
release:
jobs:
tox:
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
toxenv:
- py310,docs
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.10'
# GHA won't setup tox for us
- run: pip install tox==3.2
# there are no pre-built wheels for bsddb3, so we need to install
# its dpkg dependencies so that we can build a wheel when we're
# creating our env. Once we get rid of bsddb3 as a Python dependency,
# then we can also get rid of this dpkg
- run: sudo apt-get install --quiet --assume-yes libdb5.3-dev
# we explictly attempt to import the C extensions for some PyYAML
# functionality, so we need the LibYAML bindings provided by this
# package
- run: sudo apt-get install --quiet --assume-yes libyaml-dev
- run: tox -e ${{ matrix.toxenv }}
build_debs:
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
dist:
- jammy
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.10'
# Update package lists to ensure we have the latest information
- run: sudo apt-get update
# the container provided by GitHub doesn't include utilities
# needed for dpkg building, so we need to install `devscripts`
# to bring those in
- run: sudo apt-get install --quiet --assume-yes devscripts
- run: make itest_${{ matrix.dist }}
- uses: actions/upload-artifact@v4
with:
name: deb-${{ matrix.dist }}
path: dist/tron_*.deb
cut_release:
runs-on: ubuntu-22.04
needs: build_debs
steps:
- uses: actions/checkout@v2
- run: mkdir -p dist/
- uses: actions/download-artifact@v4
with:
name: deb-jammy
path: dist/
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/v')
with:
generate_release_notes: true
files: |
dist/tron_*.deb
fail_on_unmatched_files: true
================================================
FILE: .github/workflows/security-review.yml
================================================
# Managed by terraform, do not edit manually
name: Security Review
permissions:
pull-requests: write
contents: read
id-token: write
on:
pull_request:
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_DEV_ACCOUNT_ID }}:role/security-review-bot
aws-region: us-west-2
- uses: anthropics/claude-code-security-review@0c6a49f1fa56a1d472575da86a94dbc1edb78eda
with:
comment-pr: true
claude-api-key: "github-actions"
claude-model: "us.anthropic.claude-opus-4-6-v1"
run-every-commit: true
env:
CLAUDE_CODE_USE_BEDROCK: "1"
AWS_REGION: "us-west-2"
================================================
FILE: .gitignore
================================================
dist
build
MANIFEST
tron.egg-info
*.pyc
*._*
*.swp
*.swo
docs/_build/
.idea
.vscode
.fleet
tron.iml
docs/images/
*.dot
tronweb/js/cs/*.js
yarn.lock
tronweb_tests/spec/*.js
tronweb_tests/lib/
.tox
.tox-indocker
tron.iml
__pycache__/
.pytest_cache/
tron_state
tron.lock
manhole.sock
manhole.sock.lock
node_modules/
# Example cluster
example-cluster/config
example-cluster/MASTER.*
example-cluster/tron-repl.lock
example-cluster/tron_state*
example-cluster/manhole.sock*
example-cluster/_events/
*.stdout
*.stderr
dev/manhole.sock.lock
dev/tron.pid
dev/_events/
# Generated debian artifacts
debian/.debhelper/
debian/debhelper-build-stamp
debian/files
debian/tron
debian/tron.debhelper.log
debian/tron.postinst.debhelper
debian/tron.postrm.debhelper
debian/tron.preinst.debhelper
debian/tron.prerm.debhelper
debian/tron.substvars
================================================
FILE: .pre-commit-config.yaml
================================================
---
default_language_version:
python: python3.10
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
exclude: CHANGELOG.md
- id: check-docstring-first
- id: check-json
- id: check-yaml
- id: requirements-txt-fixer
- id: fix-encoding-pragma
args: [--remove]
- id: pretty-format-json
args: [--autofix, --indent, '4', --no-sort-keys]
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
hooks:
- id: flake8
exclude: ^docs/source/conf.py$
- repo: https://github.com/asottile/reorder_python_imports
rev: v1.9.0
hooks:
- id: reorder-python-imports
args: [--py3-plus]
- repo: https://github.com/asottile/pyupgrade
rev: v3.20.0
hooks:
- id: pyupgrade
args: [--py39-plus]
- repo: local
hooks:
- id: patch-enforce-autospec
name: mock.patch enforce autospec
description: |
This hook ensures all mock.patch invocations specify an autospec
entry: contrib/mock_patch_checker.py
language: script
files: ^tests/.*\.py$
- repo: http://github.com/psf/black
rev: 22.3.0
hooks:
- id: black
args: [--target-version, py310]
================================================
FILE: .pyautotest
================================================
test_runner_name: "testify"
================================================
FILE: .readthedocs.yaml
================================================
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# RTD defaults as of 2023-11-08
build:
os: ubuntu-22.04
tools:
python: "3.10"
# You can also specify other tool versions:
# nodejs: "20"
# rust: "1.70"
# golang: "1.20"
# Also provide downloadable zip
formats: [htmlzip]
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/source/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
# fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
# - pdf
# - epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: requirements-docs.txt
================================================
FILE: AGENTS.md
================================================
# AGENTS.md
This file provides guidance to AI coding agents working with code in this repository.
## What is Tron?
Tron is Yelp's centralized batch job scheduling system—a distributed alternative to cron for managing periodic batch processes across a cluster.
### Core Concepts
**Jobs** are DAGs (directed acyclic graphs) defined in YAML configuration. Each job contains one or more **Actions** (individual commands) with dependency relationships between them.
**JobRuns** are instances of a job execution. If a job runs daily, each execution creates a new JobRun containing **ActionRuns** for each action. Tron tracks each run independently.
### Lifecycle
```mermaid
flowchart LR
A[Startup] --> B[Restore state from DynamoDB]
B --> C[Schedule jobs]
C --> D[Track state changes]
D --> E[Save state to DynamoDB]
E --> C
```
### State Persistence
Tron persists all job and run state to DynamoDB. 101 consecutive save errors triggers intentional crash (prevents running degraded).
```mermaid
flowchart LR
A[State change] --> B[Buffer]
B -->|buffer full| C[Save queue]
C --> D[Pop from queue]
D --> E[Delete existing entries]
E --> F[Partition into chunks]
F --> G[Batch write to DynamoDB]
G -->|failure| C
```
### Execution Backends
- **Kubernetes**: Primary execution backend
- **SSH**: Legacy backend for remote command execution, do not extend
- **Mesos**: Deprecated, do not extend
## Project Structure
```
tron/
├── core/ # Job, Action, JobRun, scheduling, dependency graphs
├── config/ # YAML config parsing and schema definitions
├── serialize/ # State persistence (DynamoDB, shelve backends)
├── api/ # REST API endpoints and adapters
├── kubernetes.py # Kubernetes execution backend
└── mesos.py # Deprecated - do not modify
tronweb/ # Web UI (CoffeeScript/Backbone.js)
bin/ # CLI: trond, tronctl, tronview, tronfig
```
## Testing
Tox manages the virtualenv in `.tox/py310/`. Use `make test` for the full suite, or iterate with pytest directly:
```bash
.tox/py310/bin/pytest tests/path/to/test.py -x
```
## Development Guardrails
### High-risk areas
**DynamoDB/Persistence changes:**
- Pickle deserialization is still active—deleting or renaming persisted classes/fields breaks restore
- Reverting changes that add new persisted fields is NOT safe
- Writes batch 8 partitions at a time; large jobs needing more can be partially written if a later batch fails
**Job/action schema changes** require updates in two repos:
- Tron: `tron/config/schema.py`, `tron/core/action.py` (including `from_json`/`to_json`)
- PaaSTA: `paasta_tools/cli/schemas/tron_schema.json`, `paasta_tools/tron_tools.py`
- Plus: tests in both repos, and any code that consumes the new field
**MASTER config changes**:
- `tron/config/schema.py` — Add field to config object
- `tron/config/config_parse.py` — Add default value and validator
- Plus: tests, and any code that consumes the new config value
Reverting config changes is risky: new params get written to MASTER.yaml on disk, so reverting code requires manual config cleanup on servers.
### Do not modify
- `tron/mesos.py` — Deprecated
- `tron/ssh.py` - Deprecated
- `tron/node.py` - Deprecated
- DynamoDB schema without approval
================================================
FILE: CODEOWNERS
================================================
# NOTE: "we" in this file will refer to the Compute Infrastructure team at Yelp
* @Yelp/paasta
#
# prevent cheeky modifications :)
CODEOWNERS @Yelp/paasta
================================================
FILE: LICENSE.txt
================================================
Copyright 2010-2012 Yelp
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: MANIFEST.in
================================================
include *.txt
include *.md
include Makefile
include tron/default_config.yaml
include tron/logging.conf
include tron/named_config_template.yaml
recursive-include tests *.py *.yaml
recursive-include docs *.rst *.yaml *.1 *.8
recursive-include tronweb *
recursive-exclude tronweb *.coffee
================================================
FILE: Makefile
================================================
# Edit this release and run "make release"
RELEASE=3.10.0
SHELL=/bin/bash
DOCKER_RUN = docker run -t -v $(CURDIR):/work:rw -v $(CURDIR)/.tox-indocker:/work/.tox:rw
UID:=$(shell id -u)
GID:=$(shell id -g)
ifeq ($(findstring .yelpcorp.com,$(shell hostname -f)), .yelpcorp.com)
PAASTA_ENV ?= YELP
else
PAASTA_ENV ?= $(shell hostname --fqdn)
endif
NOOP = true
ifeq ($(PAASTA_ENV),YELP)
export PIP_INDEX_URL ?= http://169.254.255.254:20641/$*/simple/
ADD_MISSING_DEPS_MAYBE:=-diff --unchanged-line-format= --old-line-format= --new-line-format='%L' ./requirements.txt ./yelp_package/extra_requirements_yelp.txt >> ./requirements.txt
else
export PIP_INDEX_URL ?= https://pypi.python.org/simple
ADD_MISSING_DEPS_MAYBE:=$(NOOP)
endif
.PHONY : all clean tests docs dev
-usage:
@echo "make test - Run tests"
@echo "make deb_jammy - Generate jammy deb package"
@echo "make itest_jammy - Run tests and integration checks"
@echo "make _itest_jammy - Run only integration checks"
@echo "make release - Prepare debian info for new release"
@echo "make clean - Get rid of scratch and byte files"
@echo "make dev - Get a local copy of trond running in debug mode in the foreground"
docker_%:
@echo "Building docker image for $*"
[ -d dist ] || mkdir -p dist
cd ./yelp_package/$* && docker build --build-arg PIP_INDEX_URL=${PIP_INDEX_URL} -t tron-builder-$* .
deb_%: clean docker_% coffee_%
@echo "Building deb for $*"
# backup these files so we can temp modify them
cp requirements.txt requirements.txt.old
$(ADD_MISSING_DEPS_MAYBE)
$(DOCKER_RUN) -e PIP_INDEX_URL=${PIP_INDEX_URL} tron-builder-$* /bin/bash -c ' \
dpkg-buildpackage -d && \
mv ../*.deb dist/ && \
rm -rf debian/tron \
'
# restore the backed up files
mv requirements.txt.old requirements.txt
coffee_%: docker_%
@echo "Building tronweb"
$(DOCKER_RUN) tron-builder-$* /bin/bash -c ' \
rm -rf tronweb/js/cs && \
mkdir -p tronweb/js/cs && \
coffee -o tronweb/js/cs/ -c tronweb/coffee/ \
'
test:
tox -e py310
test_in_docker_%: docker_%
$(DOCKER_RUN) tron-builder-$* python3.10 -m tox -vv -e py310
tox_%:
tox -e $*
_itest_%:
$(DOCKER_RUN) ubuntu:$* /work/itest.sh
debitest_%: deb_% _itest_%
@echo "Package for $* looks good"
itest_%: debitest_%
@echo "itest $* OK"
dev:
SSH_AUTH_SOCK=$(SSH_AUTH_SOCK) .tox/py310/bin/trond --debug --working-dir=dev -l logging.conf --host=0.0.0.0
example_cluster:
tox -e example-cluster
yelpy:
.tox/py310/bin/pip install -r yelp_package/extra_requirements_yelp.txt
# 1. Bump version at the top of this file
# 2. `make release`
VERSION = $(firstword $(subst -, ,$(RELEASE) ))
LAST_COMMIT_MSG = $(shell git log -1 --pretty=%B | sed -e 's/\x27/"/g')
release:
@if [[ "$$(git status --porcelain --untracked-files=no :^/Makefile)" != '' ]]; then echo "Error: Working directory is not clean; only changes to Makefile are allowed when cutting a release."; exit 1; fi
$(eval untracked_files_tmpfile=$(shell mktemp))
git status --porcelain --untracked-files=all :^./Makefile > $(untracked_files_tmpfile)
@if [[ "$$(git status --porcelain --untracked-files=normal :/docs/source/generated)" != '' ]]; then echo "Error: Untracked files found in docs/source/generated."; exit 1; fi
@if existing_sha=$$(git rev-parse --verify --quiet v$(VERSION)); then echo "Error: tag v$(VERSION) exists and points at $$existing_sha"; exit 1; fi
@read upstream_master junk <<<"$$(git ls-remote -h origin master)" && if ! git merge-base --is-ancestor $$upstream_master HEAD; then echo "Error: HEAD is missing commits from origin/master ($$upstream_master)."; exit 1; fi
dch -v $(RELEASE) --distribution jammy --changelog ./debian/changelog $$'$(VERSION) tagged with \'make release\'\rCommit: $(LAST_COMMIT_MSG)'
sed -i -e "s/__version__ = .*/__version__ = \"$(VERSION)\"/" ./tron/__init__.py
make docs || true
git add ./Makefile ./debian/changelog ./tron/__init__.py ./docs/source/generated/
git commit -m "Released $(RELEASE) via make release"
if [[ "$$(git status --porcelain --untracked-files=all)" != "$$(<$(untracked_files_tmpfile))" ]]; then echo "Error: automatic git commit left some files uncommitted. Fix the git commit command in ./Makefile to include any automatically generated files that it is currently missing."; exit 1; fi
git tag v$(VERSION)
git push --atomic origin master v$(VERSION)
docs:
tox -r -e docs
man:
which $(SPHINXBUILD) >/dev/null && $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(DOCS_DIR) $(DOCS_DIR)/source/man || true
@echo
@echo "Build finished. The manual pages are in $(DOCS_BUILDDIR)/source/man."
clean:
rm -rf tronweb/js/cs
find . -name '*.pyc' -delete
================================================
FILE: OWNERS
================================================
---
teams:
- Compute Infra <compute-infra@yelp.com>
================================================
FILE: README.md
================================================
Tron - Batch Scheduling System
==============================
[](https://github.com/Yelp/Tron/actions/workflows/ci.yml)
[](http://tron.readthedocs.io/en/latest/?badge=latest)
Tron is a centralized system for managing periodic batch processes
across a cluster. If you find [cron](http://en.wikipedia.org/wiki/Cron) or
[fcron](http://fcron.free.fr/) to be insufficient for managing complex work
flows across multiple computers, Tron might be for you.
Install with:
> sudo pip install tron
Or look at the [tutorial](http://tron.readthedocs.io/en/latest/tutorial.html).
The full documentation is available [on ReadTheDocs](http://tron.readthedocs.io/en/latest/).
Versions / Roadmap
------------------
Tron is changing and under active development.
It is being transformed from an ssh-based execution engine to be compatible with running on [Kubernetes
](https://kubernetes.io/docs/concepts/overview/).
Tron development is specifically targeting Yelp's needs and not designed to be
a general solution for other companies.
Contributing
------------
Read [Working on Tron](http://tron.readthedocs.io/en/latest/developing.html) and
start sending pull requests!
Any issues should be posted [on Github](http://github.com/Yelp/Tron/issues).
BerkeleyDB on Mac OS X
----------------------
$ brew install berkeley-db
$ export BERKELEYDB_DIR=$(brew --cellar)/berkeley-db/<installed version>
$ export YES_I_HAVE_THE_RIGHT_TO_USE_THIS_BERKELEY_DB_VERSION=1
================================================
FILE: bin/generate_tron_tab_completion_cache
================================================
#!/usr/bin/env python
"""
print a list of all the tron jobs, to be saved as a cache for tab completion
"""
import argcomplete
from tron.commands import cmd_utils
from tron.commands.client import Client
def main():
parser = cmd_utils.build_option_parser()
argcomplete.autocomplete(parser)
args = parser.parse_args()
cmd_utils.load_config(args)
client = Client(args.server)
for job in client.jobs(include_job_runs=True, include_action_runs=True):
print(job["name"])
for run in job["runs"]:
print(run["id"])
for action in run["runs"]:
print(action["id"])
if __name__ == "__main__":
main()
================================================
FILE: bin/tronctl
================================================
#!/usr/bin/env python
"""Tron Control
Part of the command line interface to the tron daemon. Provides the interface
to controlling jobs and runs.
"""
import argparse
import asyncio
import datetime
import logging
import pprint
import sys
from collections import defaultdict
from collections.abc import Callable
from collections.abc import Generator
from typing import Any
from urllib.parse import urljoin
import argcomplete # type: ignore
from tron import __version__
from tron.commands import client
from tron.commands import cmd_utils
from tron.commands.backfill import BackfillRun
from tron.commands.backfill import confirm_backfill
from tron.commands.backfill import DEFAULT_MAX_PARALLEL_RUNS
from tron.commands.backfill import get_date_range
from tron.commands.backfill import LIMIT_MAX_PARALLEL_RUNS
from tron.commands.backfill import print_backfill_cmds
from tron.commands.backfill import print_backfill_runs_table
from tron.commands.backfill import run_backfill_for_date_range
from tron.commands.client import RequestError
from tron.commands.client import TronObjectIdentifier
from tron.commands.cmd_utils import COLOR_YELLOW
from tron.commands.cmd_utils import ExitCode
from tron.commands.cmd_utils import suggest_possibilities
from tron.commands.cmd_utils import tron_jobs_completer
from tron.commands.cmd_utils import warning_output
from tron.commands.retry import parse_deps_timeout
from tron.commands.retry import print_retries_table
from tron.commands.retry import retry_actions
from tron.commands.retry import RetryAction
COMMAND_HELP = (
(
"start",
"job name, job run id, or action id",
"Start the selected job, job run, or action. Creates a new job run if starting a job.",
),
(
"rerun",
"job run id",
"Start a new job run with the same start time command context as the given job run.",
),
(
"retry",
"action id",
"Re-run a job action within an existing job run. Uses latest code/config except the command by default. Add --use-latest-command to use the latest command.",
),
("recover", "action id", "Ask Tron to start tracking an UNKNOWN action run again"),
("cancel", "job run id", "Cancel the selected job run."),
(
"backfill",
"job name",
"Start job runs for a particular date range",
),
(
"disable",
"job name",
"Disable selected job and cancel any outstanding runs. WARNING: you *must* disable the job in yelpsoa-configs to guarantee it will not be re-enabled.",
),
("enable", "job name", "Enable the selected job and schedule the next run"),
(
"fail",
"job run or action id",
"Mark an UNKNOWN job or action as failed. Does not publish action triggers.",
),
(
"success",
"job run or action id",
"Mark an UNKNOWN job or action as having succeeded. Will publish action triggers.",
),
(
"skip",
"action id",
"Skip a failed action, unblocks dependent actions. Does *not* publish action triggers.",
),
(
"skip-and-publish",
"action id",
"Skip a failed action, unblocks dependent actions. *Does* publish action triggers.",
),
("stop", "action id", "Stop the action run (SIGTERM)"),
("kill", "action id", "Force kill the action run (SIGKILL)"),
("move", "job name", "Rename a job"),
("publish", "trigger id", "Publish actionrun trigger to kick off downstream jobs"),
("discard", "trigger id", "Discard existing actionrun trigger"),
("version", None, "Print tron client and server versions"),
)
log = logging.getLogger("tronctl")
def parse_date(date_string):
return datetime.datetime.strptime(date_string, "%Y-%m-%d")
def parse_cli():
parser = cmd_utils.build_option_parser()
subparsers = parser.add_subparsers(dest="command", title="commands", help="Tronctl command to run", required=True)
cmd_parsers = {}
for cmd_name, id_help_text, desc in COMMAND_HELP:
cmd_parsers[cmd_name] = subparsers.add_parser(cmd_name, help=desc, description=desc)
if id_help_text:
cmd_parsers[cmd_name].add_argument(
"id", nargs="*", help=id_help_text
).completer = cmd_utils.tron_jobs_completer
# HACK: this is slightly funky since we already add --verbose in cmd_utils.build_option_parser(),
# but that requires something like tronctl --verbose start JOB rather than tronctl start -v JOB
cmd_parsers[cmd_name].add_argument(
"-v",
"--verbose",
action="count",
help="Verbose logging",
default=None,
)
# start
cmd_parsers["start"].add_argument(
"--run-date",
type=parse_date,
dest="run_date",
help="What the run-date should be set to",
)
# backfill
backfill_parser = cmd_parsers["backfill"]
mutex_dates_group = backfill_parser.add_mutually_exclusive_group(required=True)
mutex_dates_group.add_argument(
"--start-date",
type=parse_date,
dest="start_date",
help="First run-date to backfill",
)
backfill_parser.add_argument(
"--end-date",
type=parse_date,
dest="end_date",
help=(
"Last run-date to backfill (note: many jobs operate on date-1), "
"assuming --start-date is set. This date is inclusive. Defaults to today."
),
)
backfill_parser.add_argument(
"--descending",
action="store_true",
default=False,
help=(
"If set, backfill from end date to start date. Otherwise, "
"the default is to backfill from start date to end date."
),
)
mutex_dates_group.add_argument(
"-d",
"--dates",
type=lambda v: [parse_date(date_str.strip()) for date_str in v.split(",")],
dest="dates",
help=(
"List of comma-separated dates to run backfills on. "
"Backfills will be executed for dates in the order they are presented."
),
)
backfill_parser.add_argument(
"-P",
"--max-parallel",
type=int,
dest="max_parallel",
default=DEFAULT_MAX_PARALLEL_RUNS,
help=(
"The max number of dates that can be backfilled in parallel. "
"Before setting, consider how much in resources your job needs. "
"If it needs a lot, keep this number low, because there may not be "
"enough resources in the cluster too satisfy the demand, which can "
"adversely affect other jobs. "
"The default is %(default)s."
),
)
backfill_parser.add_argument(
"--fail-on-error",
dest="fail_on_error",
action="store_true",
default=False,
help=(
"If set, the overall backfill will fail immediately if a backfill "
"for a single date fails. All in-progress backfills will cancelled. "
"If a single backfill is still considered successful it was otherwise "
"cancelled or skipped by the user. "
"By default, individual backfill failures are ignored."
),
)
backfill_parser.add_argument(
"--dry-run",
action="store_true",
default=False,
help="Prints the equivalent `tronctl start` commands for the backfill",
)
# retry
retry_parser = cmd_parsers["retry"]
retry_parser.add_argument(
"--use-latest-command",
action="store_true",
default=False,
help="Use the latest command in tronfig rather than the original command when the action run was created",
)
retry_parser.add_argument(
"--wait-for-deps",
type=parse_deps_timeout,
default=0,
dest="deps_timeout",
help=(
"Max duration to wait for upstream dependencies (upstream triggers "
"and/or same job actions) before attempting to retry. "
"If all dependencies are not done when the timeout expires, "
"this command will exit with an error, and the action will NOT be retried. "
"Must be either an int number of seconds, a human-readable/"
"pytimeparse-parsable string, or 'infinity' to wait forever. "
"Defaults to 0 (don't wait)."
),
)
argcomplete.autocomplete(parser)
args = parser.parse_args()
return args
def request(url: str, data: dict[str, Any], headers=None, method=None) -> bool:
# We want every tronctl request to be attributable
response = client.request(url, data=data, headers=headers, method=method, user_attribution=True)
if response.error:
print(f"Error: {response.content}")
return False
print(response.content.get("result", "OK"))
return True
def event_publish(args):
for event in args.id:
# trying to publish a job run/action run id will likely print multiple warnings
# since the conditions are somewhat overlapping - only print the first one
warning_printed = False
split_event = event.split(".")
# first, let's try to catch folks trying to publish a job run or action run id as a trigger
# these will look something like NAMESPACE.JOB_NAME.RUN_NUMBER or NAMESPACE.JOB_NAME.RUN_NUMBER.ACTION_NAME
# i.e., if the 3rd element is an integer, it's one of these
if len(split_event) >= 3:
try:
int(split_event[2])
print(
warning_output(
f"\nWarning: the event id '{event}' looks like a job run or action run id rather than a trigger id!",
color=COLOR_YELLOW,
)
)
print(
warning_output(
"This is almost certainly incorrect and you want something like `tronctl publish $SERVICE.$JOB_NAME.$ACTION_NAME.$TRIGGER_NAME.$TRIGGER_VALUE`",
color=COLOR_YELLOW,
)
)
warning_printed = True
except ValueError:
pass
if len(split_event) != 5 and not warning_printed:
print(
warning_output(
f"\nWarning: '{event}' is too {'long' if len(split_event) > 5 else 'short'} and does not match the expected trigger format!",
color=COLOR_YELLOW,
)
)
print(
warning_output(
"This is almost certainly incorrect and you want something like `tronctl publish $SERVICE.$JOB_NAME.$ACTION_NAME.$TRIGGER_NAME.$TRIGGER_VALUE`",
color=COLOR_YELLOW,
)
)
yield request(
urljoin(args.server, "/api/events"),
dict(command="publish", event=event),
)
def event_discard(args):
for event in args.id:
yield request(
urljoin(args.server, "/api/events"),
dict(command="discard", event=event),
)
def _get_triggers_for_action(server: str, action_identifier: str) -> tuple[str, ...] | None:
try:
namespace, job_name, run_number, action_name = action_identifier.split(".")
except ValueError:
print(
f"Unable to fully decompose {action_identifier}: expected an identifier of the form (namespace).(job).(run).(action)"
)
return None
trigger_response = client.request(
uri=urljoin(
server,
f"/api/jobs/{namespace}.{job_name}/{run_number}/{action_name}",
),
)
if trigger_response.error:
print(f"Unable to fetch downstream triggers for {action_identifier}: {trigger_response.error}")
return None
# triggers are returned by the API as comma-separated values with a space after every comma, which is
# not automation-friendly - thus the non-standard multi-character split
triggers = trigger_response.content.get("trigger_downstreams", "").split(", ")
# the API will return an empty string for actions with no triggers to emit, but splitting '' yields [''],
# so we want to make sure that we return an empty iterable in this case
return tuple(f"{namespace}.{job_name}.{action_name}.{trigger}" for trigger in triggers if trigger)
def skip_and_publish(server: str, tron_id: TronObjectIdentifier, identifier: str) -> bool:
all_success = True
print(f"Skipping {identifier}...")
if request(
url=urljoin(server, tron_id.url),
data={"command": "skip"},
):
print(f"Successfully skipped {identifier}.")
print(f"\nFetching triggers to publish for {identifier}...")
# a single action can have 0..N triggers to publish and these can be arbitrarily named, so we need to
# query the API and figure out what triggers exist
triggers = _get_triggers_for_action(server=server, action_identifier=identifier)
if triggers is None:
print(f"\nEncountered error getting triggers to publish for {identifier}!")
return False
elif not triggers:
print(f"{identifier} has no triggers to publish - just skipping instead.")
# TODO: should we check this up-front and refuse to skip if there are no triggers that will be
# published rather than carry on under the assumption that the user copy-pasted/typo'd the identifier?
return True
else:
# TODO: this loop should use event_publish(), but we'd need to refactor how the CLI works and stop passing
# around the full set of args everywhere to do so
print("\nTriggers to publish:")
print("\n".join(f" * {trigger}" for trigger in triggers) + "\n")
for trigger in triggers:
print(f"Publishing trigger {trigger}...")
if not request(
url=urljoin(server, "/api/events"),
data={"command": "publish", "event": trigger},
):
print(
f"Failed to publish trigger {trigger} - you may want to retry this command or manually publish the trigger!"
)
all_success = False
else:
print(f"\nFailed to skip {identifier}!")
return False
return all_success
def control_objects(args: argparse.Namespace):
tron_client = client.Client(args.server, user_attribution=True)
url_index = tron_client.index()
for identifier in args.id:
try:
tron_id = client.get_object_type_from_identifier(
url_index,
identifier,
)
except ValueError as e:
possibilities = list(
tron_jobs_completer(prefix="", client=tron_client),
)
suggestions = suggest_possibilities(
word=identifier,
possibilities=possibilities,
)
raise SystemExit(f"Error: {e}{suggestions}")
if args.command == "skip-and-publish":
# this command is more of a pseudo-command - skip and publish are handled in two different resources
# and changing the API would be painful, so instead we call skip + publish separately from the client
# (i.e., this file) to implement this functionality
yield skip_and_publish(args.server, tron_id, identifier)
else:
data = dict(command=args.command)
if args.command == "start" and args.run_date:
data["run_time"] = str(args.run_date)
yield request(urljoin(args.server, tron_id.url), data)
# NOTE: ideally we'd add this message in the JobController handle_command() function, but having the API return terminal escape codes
# sounds like a bad idea, so we're doing it here instead
if args.command == "disable":
print(
warning_output(
"WARNING: jobs disabled with tronctl disable are *NOT* guaranteed to stay disabled. You must disable the job in yelpsoa-configs to guarantee it will not be re-enabled."
)
)
def retry(args):
if args.deps_timeout != RetryAction.NO_TIMEOUT:
deps_timeout_str = "forever" # timeout = -1 (RetryAction.WAIT_FOREVER)
if args.deps_timeout > 0:
deps_timeout_str = "up to " + str(datetime.timedelta(seconds=args.deps_timeout))
print(
f"We will wait {deps_timeout_str} for all upstream triggers to be published "
"and required actions to finish successfully before issuing retries for the "
"following actions:"
)
print()
pprint.pprint(args.id)
print()
retries = retry_actions(args.server, args.id, args.use_latest_command, args.deps_timeout)
print_retries_table(retries)
yield all([r.succeeded for r in retries])
def move(args):
try:
old_name = args.id[0]
new_name = args.id[1]
except IndexError as e:
raise SystemExit(f"Error: Move command needs two arguments.\n{e}")
tron_client = client.Client(args.server, user_attribution=True)
url_index = tron_client.index()
job_index = url_index["jobs"]
if old_name not in job_index.keys():
raise SystemExit(f"Error: {old_name} doesn't exist")
if new_name in job_index.keys():
raise SystemExit(f"Error: {new_name} exists already")
data = dict(command="move", old_name=old_name, new_name=new_name)
yield request(urljoin(args.server, "/api/jobs"), data)
def backfill(args):
if not args.id:
print("Error: must provide at least one id argument")
yield False
if args.max_parallel > LIMIT_MAX_PARALLEL_RUNS:
raise SystemExit(
f"The flag --max-parallel exceeds the allowed limit of {LIMIT_MAX_PARALLEL_RUNS}. "
+ "Please reach out to the Tron team if you need to run backfills with higher limits."
)
if args.start_date:
if args.end_date is None:
args.end_date = datetime.datetime.today()
dates = get_date_range(args.start_date, args.end_date, descending=args.descending)
else:
dates = args.dates
date_strs = [d.date().isoformat() for d in dates]
job_name = args.id[0]
if args.dry_run:
print_backfill_cmds(job_name, date_strs)
yield True
else:
if confirm_backfill(job_name, date_strs):
loop = asyncio.get_event_loop()
try:
backfill_runs = loop.run_until_complete(
run_backfill_for_date_range(
args.server,
job_name,
dates,
max_parallel=args.max_parallel,
ignore_errors=(not args.fail_on_error),
),
)
finally:
loop.close()
print_backfill_runs_table(backfill_runs)
yield all(br.run_state in BackfillRun.SUCCESS_STATES for br in backfill_runs)
def tron_version(args):
local_version = __version__
print(f"Tron client version: {local_version}")
response = client.request(urljoin(args.server, "/api/status"))
if response.error:
print(f"Error: {response.content}")
yield
server_version = response.content.get("version", "unknown")
print(f"Tron server version: {server_version}")
if server_version != local_version:
print("Warning: client and server versions should match")
yield
yield True
COMMANDS: dict[str, Callable[[argparse.Namespace], Generator[bool, None, None]]] = defaultdict(
lambda: control_objects,
publish=event_publish,
discard=event_discard,
backfill=backfill,
move=move,
retry=retry,
version=tron_version,
)
def main():
"""run tronctl"""
args = parse_cli()
cmd_utils.load_config(args)
# NOTE: we do this after load_configs() since load_config() may set some logging defaults that we want to override
desired_level = cmd_utils.setup_logging(args)
logging.getLogger().setLevel(desired_level)
cmd = COMMANDS[args.command]
try:
for ret in cmd(args):
if not ret:
sys.exit(ExitCode.fail)
except RequestError as err:
print(
f"Error connecting to the tron server ({args.server}): {err}",
file=sys.stderr,
)
sys.exit(ExitCode.fail)
if __name__ == "__main__":
main()
================================================
FILE: bin/tronctl_tabcomplete.sh
================================================
if [[ -n ${ZSH_VERSION-} ]]; then
autoload -U +X bashcompinit && bashcompinit
fi
# This magic eval enables tab-completion for tron commands
# http://argcomplete.readthedocs.io/en/latest/index.html#synopsis
eval "$(/opt/venvs/tron/bin/register-python-argcomplete tronctl)"
================================================
FILE: bin/trond
================================================
#!/usr/bin/env python
""" Start the Tron server daemon."""
import argparse
import faulthandler
import logging
import os
import time
import traceback
import pkg_resources
import tron
from tron import trondaemon
from tron.commands import cmd_utils
from tron.config import manager
log = logging.getLogger(__name__)
DEFAULT_CONF = "default_config.yaml"
DEFAULT_CONF_PATH = "config/"
DEFAULT_WORKING_DIR = "/var/lib/tron/"
DEFAULT_LOCKFILE = "tron.lock"
DEFAULT_LOCKPATH = "/var/run/" + DEFAULT_LOCKFILE
def parse_cli():
parser = argparse.ArgumentParser()
parser.add_argument(
"--version",
action="version",
version=f"{parser.prog} {tron.__version__}",
)
parser.add_argument(
"-w",
"--working-dir",
default=DEFAULT_WORKING_DIR,
help="Working directory for the Tron daemon, default %(default)s",
)
parser.add_argument(
"-c",
"--config-path",
default=DEFAULT_CONF_PATH,
help="File path to the Tron configuration file",
)
parser.add_argument(
"--nodaemon",
action="store_true",
default=False,
help="[DEPRECATED] Disable daemonizing, default %(default)s",
)
parser.add_argument( # for backwards compatibility
"--pid-file",
help="[DEPRECATED] File path to pid file. Use --lock-file instead.",
)
parser.add_argument(
"--lock-file",
help="File path to lock file, defaults to %s if working directory "
"is default. Otherwise defaults to <working dir>/%s" % (DEFAULT_LOCKPATH, DEFAULT_LOCKFILE),
)
logging_group = parser.add_argument_group("logging", "")
logging_group.add_argument(
"--log-conf",
"-l",
help="File path to a custom logging.conf",
)
logging_group.add_argument(
"-v",
"--verbose",
action="count",
default=0,
help="Verbose logging. Repeat for more verbosity.",
)
logging_group.add_argument(
"--debug",
action="store_true",
help="Debug mode, extra error reporting, no daemonizing",
)
api_group = parser.add_argument_group("Web Service API", "")
api_group.add_argument(
"--port",
"-P",
dest="listen_port",
type=int,
help="TCP port number to listen on, default %(default)s",
default=cmd_utils.DEFAULT_PORT,
)
api_group.add_argument(
"--host",
"-H",
dest="listen_host",
help="Hostname to listen on, default %(default)s",
default=cmd_utils.DEFAULT_HOST,
)
requirement = pkg_resources.Requirement.parse("tron")
api_group.add_argument(
"--web-path",
default=pkg_resources.resource_filename(
requirement,
"tronweb",
),
help="Path to static web resources, default %(default)s.",
)
args = parser.parse_args()
args.working_dir = os.path.abspath(args.working_dir)
if args.log_conf:
args.log_conf = os.path.join(args.working_dir, args.log_conf)
if not os.path.exists(args.log_conf):
parser.error("Logging config file not found: %s" % args.log_conf)
if not args.lock_file:
if args.pid_file: # for backwards compatibility
args.lock_file = args.pid_file
elif args.working_dir == DEFAULT_WORKING_DIR:
args.lock_file = DEFAULT_LOCKPATH
else:
args.lock_file = DEFAULT_LOCKFILE
args.lock_file = os.path.join(args.working_dir, args.lock_file)
args.config_path = os.path.join(
args.working_dir,
args.config_path,
)
return args
def create_default_config(config_path):
"""Create a default empty configuration for first time installs"""
default = pkg_resources.resource_string(tron.__name__, DEFAULT_CONF)
manager.create_new_config(config_path, default)
def setup_environment(args):
"""Setup the working directory and config environment."""
if not os.path.exists(args.working_dir):
os.makedirs(args.working_dir)
if not os.path.isdir(args.working_dir) or not os.access(args.working_dir, os.R_OK | os.W_OK | os.X_OK):
msg = "Error, can't access working directory %s" % args.working_dir
raise SystemExit(msg)
# Attempt to create a default config if config is missing
if not os.path.exists(args.config_path):
try:
create_default_config(args.config_path)
except OSError as e:
msg = "Error creating default configuration at %s: %s"
log.debug(traceback.format_exc())
raise SystemExit(msg % (args.config_path, e))
if not os.access(args.config_path, os.R_OK | os.W_OK):
msg = "Error opening configuration %s: Missing Permissions"
raise SystemExit(msg % args.config_path)
def main():
args = parse_cli()
boot_time = time.time()
setup_environment(args)
trond = trondaemon.TronDaemon(args)
trond.run(boot_time)
if __name__ == "__main__":
# print tracebacks on signals/faults
# NOTE: you likely want to read https://docs.python.org/3/library/faulthandler.html
# as these tracebacks will look slightly different
faulthandler.enable()
try:
main()
# this is a little weird, but every now and then we're seeing a mysterious tron exit
# that doesn't seem to correspond with anything else - let's catch BaseException
# (and therefore SystemExit) in case anything is calling sys.exit() since there's no
# traceback when we see this
except (
BaseException,
# technically, we really only need to catch BaseException - but let's be extra-paranoid
Exception,
):
traceback.print_exc()
raise
================================================
FILE: bin/tronfig
================================================
#!/usr/bin/env python
import logging
import os
import shutil
import sys
import tempfile
import traceback
from tron.commands import cmd_utils
from tron.commands.client import Client
from tron.config import config_parse
from tron.config import ConfigError
from tron.config import manager
from tron.config import schema
log = logging.getLogger("tronfig")
def parse_cli():
parser = cmd_utils.build_option_parser()
parser.add_argument(
"-p",
"--print",
action="store_true",
dest="print_config",
help="Print config to stdout, rather than uploading",
)
parser.add_argument(
"-C",
"--check",
action="store_true",
dest="check",
help="Upload and check configuration, don't apply, "
"useful when you want to verify if tron daemon "
"will accept your configuration.",
)
parser.add_argument(
"-d",
"--delete",
action="store_true",
help="Delete the configuration for this namespace",
)
parser.add_argument(
"-V",
"--validate",
action="store_true",
dest="validate",
help="Only validate configuration, don't upload, "
"useful for verifying config locally. If namespace "
"is not specified, it will be derived from file "
"name, if any.",
)
parser.add_argument(
"-D",
"--validate-dir",
action="store_true",
dest="validate_dir",
help="Full validation of a folder, don't upload, " "same as -V but checks for more edge-cases",
)
parser.add_argument(
"-n",
"--namespace",
action="store",
help="Alternate namespace to use",
)
parser.add_argument(
"-m",
"--master-config",
action="store",
dest="master_config",
help="Source of master configuration file",
)
parser.add_argument("source")
return parser.parse_args()
def upload_config(client, config_name, contents, config_hash, check=False):
response = client.config(
config_name,
config_data=contents,
config_hash=config_hash,
check=check,
)
if "error" in response:
log.error(response["error"])
return False
print("Configuration uploaded successfully", file=sys.stderr)
return True
def validate(config_name, config_content, master_content=None):
try:
config_data = manager.from_string(config_content)
master_data = (
manager.from_string(
master_content,
)
if master_content
else None
)
config_parse.validate_fragment(
name=config_name,
fragment=config_data,
master_config=master_data,
)
except ConfigError as e:
return str(e)
def delete_config(client, config_name):
if config_name == schema.MASTER_NAMESPACE:
log.error(
"Deleting MASTER namespace is not allowed. Name must be specified.",
)
return
response = input(
f"This will delete the configuration for the {config_name} namespace. Proceed? (y/n): ",
)
if response[:1].lower() != "y":
return
config_hash = client.config(config_name)["hash"]
if upload_config(client, config_name, "", config_hash):
return
raise SystemExit("tronfig deletion failed")
def validate_dir(path):
try:
manifest_dir = tempfile.mkdtemp()
manifest = manager.ManifestFile(manifest_dir)
manifest.create()
for fname in os.listdir(path):
name, ext = os.path.splitext(fname)
if ext == ".yaml":
namespace = name
manifest.add(namespace, os.path.join(path, fname))
config_manager = manager.ConfigManager(path, manifest)
config_manager.load()
except ConfigError as e:
traceback.print_exc()
return str(e)
finally:
if manifest_dir:
shutil.rmtree(manifest_dir)
def get_config_input(namespace, source):
if source == "-":
source_io = sys.stdin
if not namespace:
namespace = schema.MASTER_NAMESPACE
else:
source_io = open(source)
if not namespace:
name, _ = os.path.splitext(os.path.basename(source))
namespace = name
content = source_io.read()
return namespace, content
if __name__ == "__main__":
args = parse_cli()
cmd_utils.setup_logging(args)
cmd_utils.load_config(args)
if args.validate or args.validate_dir:
if args.validate:
name, content = get_config_input(args.namespace, args.source)
master_content = None
if args.master_config:
_, master_content = get_config_input(
schema.MASTER_NAMESPACE,
args.master_config,
)
result = validate(
config_name=name,
config_content=content,
master_content=master_content,
)
elif args.validate_dir:
result = validate_dir(args.source)
if not result:
print("OK")
sys.exit(0)
else:
print(result)
sys.exit(1)
client = Client(args.server)
if args.print_config:
content = client.config(args.source)["config"]
if type(content) is not bytes:
content = content.encode("utf8")
os.write(sys.stdout.fileno(), content)
elif args.delete:
delete_config(client, args.source)
else:
namespace, content = get_config_input(args.namespace, args.source)
config_hash = client.config(namespace)["hash"]
result = validate(namespace, content)
if result:
print(result)
sys.exit(1)
if upload_config(
client,
namespace,
content,
config_hash,
check=args.check,
):
sys.exit(0)
print("Uploading failed")
sys.exit(1)
================================================
FILE: bin/tronrepl
================================================
#!/usr/bin/env python
""" Start the Tron server daemon."""
import argparse
import logging
import os
import traceback
import IPython
import pkg_resources
import tron.mcp
from tron import trondaemon
from tron.commands import cmd_utils
from tron.config import manager
log = logging.getLogger(__name__)
DEFAULT_CONF = "default_config.yaml"
DEFAULT_CONF_PATH = "config/"
DEFAULT_WORKING_DIR = "/var/lib/tron/"
DEFAULT_LOCKFILE = "tron-repl.lock"
DEFAULT_LOCKPATH = "/var/run/" + DEFAULT_LOCKFILE
def parse_cli():
parser = argparse.ArgumentParser()
parser.add_argument(
"--version",
action="version",
version=f"{parser.prog} {tron.__version__}",
)
parser.add_argument(
"-w",
"--working-dir",
default=DEFAULT_WORKING_DIR,
help="Working directory for the Tron daemon, default %(default)s",
)
parser.add_argument(
"-c",
"--config-path",
default=DEFAULT_CONF_PATH,
help="File path to the Tron configuration file",
)
parser.add_argument(
"--nodaemon",
action="store_true",
default=False,
help="[DEPRECATED] Disable daemonizing, default %(default)s",
)
parser.add_argument( # for backwards compatibility
"--pid-file",
help="[DEPRECATED] File path to pid file. Use --lock-file instead.",
)
parser.add_argument(
"--lock-file",
help="File path to lock file, defaults to %s if working directory "
"is default. Otherwise defaults to <working dir>/%s" % (DEFAULT_LOCKPATH, DEFAULT_LOCKFILE),
)
logging_group = parser.add_argument_group("logging", "")
logging_group.add_argument(
"--log-conf",
"-l",
help="File path to a custom logging.conf",
)
logging_group.add_argument(
"-v",
"--verbose",
action="count",
default=0,
help="Verbose logging. Repeat for more verbosity.",
)
logging_group.add_argument(
"--debug",
action="store_true",
help="Debug mode, extra error reporting, no daemonizing",
)
api_group = parser.add_argument_group("Web Service API", "")
api_group.add_argument(
"--port",
"-P",
dest="listen_port",
type=int,
help="TCP port number to listen on, default %(default)s",
default=cmd_utils.DEFAULT_PORT,
)
api_group.add_argument(
"--host",
"-H",
dest="listen_host",
help="Hostname to listen on, default %(default)s",
default=cmd_utils.DEFAULT_HOST,
)
requirement = pkg_resources.Requirement.parse("tron")
api_group.add_argument(
"--web-path",
default=pkg_resources.resource_filename(
requirement,
"tronweb",
),
help="Path to static web resources, default %(default)s.",
)
args = parser.parse_args()
args.working_dir = os.path.abspath(args.working_dir)
if args.log_conf:
args.log_conf = os.path.join(args.working_dir, args.log_conf)
if not os.path.exists(args.log_conf):
parser.error("Logging config file not found: %s" % args.log_conf)
if not args.lock_file:
if args.pid_file: # for backwards compatibility
args.lock_file = args.pid_file
elif args.working_dir == DEFAULT_WORKING_DIR:
args.lock_file = DEFAULT_LOCKPATH
else:
args.lock_file = DEFAULT_LOCKFILE
args.lock_file = os.path.join(args.working_dir, args.lock_file)
args.config_path = os.path.join(
args.working_dir,
args.config_path,
)
return args
def create_default_config(config_path):
"""Create a default empty configuration for first time installs"""
default = pkg_resources.resource_string(tron.__name__, DEFAULT_CONF)
manager.create_new_config(config_path, default)
def setup_environment(args):
"""Setup the working directory and config environment."""
if not os.path.exists(args.working_dir):
os.makedirs(args.working_dir)
if not os.path.isdir(args.working_dir) or not os.access(args.working_dir, os.R_OK | os.W_OK | os.X_OK):
msg = "Error, can't access working directory %s" % args.working_dir
raise SystemExit(msg)
# Attempt to create a default config if config is missing
if not os.path.exists(args.config_path):
try:
create_default_config(args.config_path)
except OSError as e:
msg = "Error creating default configuration at %s: %s"
log.debug(traceback.format_exc())
raise SystemExit(msg % (args.config_path, e))
if not os.access(args.config_path, os.R_OK | os.W_OK):
msg = "Error opening configuration %s: Missing Permissions"
raise SystemExit(msg % args.config_path)
def main():
args = parse_cli()
setup_environment(args)
trond = trondaemon.TronDaemon(args) # noqa: F841
trond.mcp = tron.mcp.MasterControlProgram(
trond.options.working_dir,
trond.options.config_path,
)
trond.mcp._load_config()
# trond.mcp.restore_state(trond.mcp.config.load().get_master().action_runner)
# mcp = trond.mcp # noqa: F841
# store = mcp.state_watcher.state_manager._impl # noqa: F841
print("")
print("+---------------------+")
print("| Tron REPL |")
print("| Available locals: |")
print("| - trond |")
print("+---------------------+")
print("")
IPython.embed()
if __name__ == "__main__":
main()
================================================
FILE: bin/tronview
================================================
#!/usr/bin/env python
import os
import sys
import argcomplete
from tron.commands import cmd_utils
from tron.commands import display
from tron.commands.client import Client
from tron.commands.client import get_object_type_from_identifier
from tron.commands.client import RequestError
from tron.commands.client import TronObjectType
from tron.commands.cmd_utils import ExitCode
from tron.commands.cmd_utils import suggest_possibilities
from tron.commands.cmd_utils import tron_jobs_completer
def parse_cli():
parser = cmd_utils.build_option_parser()
parser.add_argument(
"--numshown",
"-n",
type=int,
dest="num_displays",
help="Max number of jobs/job-runs shown",
default=10,
)
parser.add_argument(
"--color",
"-c",
action="store_true",
dest="display_color",
help="Display in color",
default=None,
)
parser.add_argument(
"--nocolor",
action="store_false",
dest="display_color",
help="Display without color",
default=None,
)
parser.add_argument(
"--stdout",
"-o",
action="count",
dest="stdout",
help="Solely displays stdout",
default=0,
)
parser.add_argument(
"--stderr",
"-e",
action="count",
dest="stderr",
help="Solely displays stderr",
default=0,
)
parser.add_argument(
"--events",
"-E",
action="store_true",
dest="events",
help="Display stored events",
default=0,
)
parser.add_argument(
"name",
nargs="?",
help="job name | job run id | action id",
).completer = cmd_utils.tron_jobs_completer
argcomplete.autocomplete(parser)
args = parser.parse_args()
return args
def console_height():
if not sys.stdout.isatty():
return 40
return int(os.popen("stty size", "r").read().split()[0])
def view_all(args, client):
"""Retrieve jobs and display them."""
return display.DisplayJobs().format(
client.jobs(
include_job_runs=False,
include_action_runs=False,
include_action_graph=False,
include_node_pool=False,
),
)
def view_job(args, job_id, client):
"""Retrieve details of the specified job and display"""
job_content = client.job(job_id.url, count=args.num_displays)
return display.format_job_details(job_content)
def view_job_run(args, job_run_id, client):
actions = client.job_runs(job_run_id.url)
display_action = display.DisplayActionRuns()
return display_action.format(actions)
def view_action_run(args, act_run_id, client):
content = client.action_runs(
act_run_id.url,
num_lines=args.num_displays,
)
return display.format_action_run_details(content)
obj_type_to_view_map = {
TronObjectType.job: view_job,
TronObjectType.job_run: view_job_run,
TronObjectType.action_run: view_action_run,
}
def get_view_output(name, args, client):
url_index = client.index()
try:
tron_id = get_object_type_from_identifier(url_index, name)
except ValueError as e:
possibilities = list(tron_jobs_completer(prefix="", client=client))
suggestions = suggest_possibilities(
word=name,
possibilities=possibilities,
)
raise SystemExit(f"Error: {e}{suggestions}")
if tron_id.type not in obj_type_to_view_map:
return
try:
return obj_type_to_view_map[tron_id.type](args, tron_id, client)
except RequestError as e:
raise SystemExit(f"Error: {e}")
def main():
"""run tronview"""
args = parse_cli()
cmd_utils.setup_logging(args)
cmd_utils.load_config(args)
display.Color.toggle(args.display_color)
client = Client(args.server)
try:
if args.events:
response = client.request("/api/events")
error = response.get("error")
if not error:
for evt in response.get("response", ["* no recorded events *"]):
print(evt)
sys.exit(ExitCode.success)
if not args.name:
output = view_all(args, client)
else:
output = get_view_output(args.name, args, client)
if not output:
print("Unrecognized identifier: %s" % args.name, file=sys.stderr)
sys.exit(ExitCode.fail)
if sys.stdout.isatty() and len(output.split("\n")) > console_height():
display.view_with_less(output, args.display_color)
else:
print(output)
except RequestError as err:
print(
f"Error connecting to the tron server ({args.server}): {err}",
file=sys.stderr,
)
sys.exit(ExitCode.fail)
if __name__ == "__main__":
main()
================================================
FILE: bin/tronview_tabcomplete.sh
================================================
if [[ -n ${ZSH_VERSION-} ]]; then
autoload -U +X bashcompinit && bashcompinit
fi
# This magic eval enables tab-completion for tron commands
# http://argcomplete.readthedocs.io/en/latest/index.html#synopsis
eval "$(/opt/venvs/tron/bin/register-python-argcomplete tronview)"
================================================
FILE: contrib/migration_script.py
================================================
#!/usr/bin/env python
"""
This script is for migrating jobs to another namespace
"""
import argparse
import subprocess
import time
from urllib.parse import urljoin
from urllib.parse import urlparse
from tron import yaml
from tron.commands import client
class bcolors:
HEADER = "\033[95m"
OKBLUE = "\033[94m"
OKGREEN = "\033[92m"
WARNING = "\033[93m"
FAIL = "\033[91m"
ENDC = "\033[0m"
BOLD = "\033[1m"
UNDERLINE = "\033[4m"
def parse_args():
parser = argparse.ArgumentParser(
description="Migrate jobs to new namespace",
)
parser.add_argument(
"--server",
required=True,
help="specify the location of tron master",
)
parser.add_argument(
"--old-ns",
required=True,
help="Old namespace",
)
parser.add_argument(
"--new-ns",
required=True,
help="New namespace",
)
parser.add_argument(
"source",
help="source file to get list of jobs",
)
parser.add_argument(
"--job",
help="Specify a single job to migrate",
)
args = parser.parse_args()
return args
def check_job_if_running(jobs_status, job_name):
for job_status in jobs_status:
if job_status["name"] == job_name:
status = job_status["status"]
if status == "running":
print(bcolors.FAIL + f"job {job_name} is still running, can not migrate" + bcolors.ENDC)
return False
elif status == "disabled":
print(bcolors.WARNING + f"job {job_name} is disabled, need to cancel it manually later" + bcolors.ENDC)
return True
else:
print(bcolors.OKGREEN + f"job {job_name} is not running, can migrate" + bcolors.ENDC)
return True
print(bcolors.FAIL + f"Can not find the job {job_name}" + bcolors.ENDC)
return False
def command_jobs(command, jobs, args, ns=None):
"""This function run tronctl command for the jobs
command: the tronctl command it will run
jobs: a list of jobs
args: the args for this script
ns: the namespace to use as the prefix for each job, if None, the scrip would use args.old_ns instead
"""
data = {"command": command}
command_flag = True
for job in jobs:
if ns is not None:
job_name = ns + "." + job["name"]
else:
job_name = args.old_ns + "." + job["name"]
if command == "move":
data = {
"command": command,
"old_name": args.old_ns + "." + job["name"],
"new_name": args.new_ns + "." + job["name"],
}
uri = urljoin(args.server, "api/jobs")
job_name = args.new_ns + "." + job["name"]
else:
data = {"command": command}
uri = urljoin(args.server, "api/jobs/" + job_name)
response = client.request(uri, data=data)
if response.error:
print(bcolors.FAIL + f"Failed to {command} {job_name}" + bcolors.ENDC)
command_flag = False
else:
print(bcolors.OKGREEN + f"Succeed to {command} {job_name}" + bcolors.ENDC)
return command_flag
def ssh_command(hostname, command):
print(bcolors.BOLD + f"Executing the command: ssh -A {hostname} {command}" + bcolors.ENDC)
ssh = subprocess.Popen(
["ssh", "-A", hostname, command],
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
exitcode = ssh.wait()
result = ssh.stdout.readlines()
error = ssh.stderr.readlines()
if exitcode != 0:
print(bcolors.FAIL + f"Execute command {command} failed: {error}" + bcolors.ENDC)
exit(exitcode)
return result
def main():
args = parse_args()
filename = args.source
hostname = urlparse(args.server).hostname
if filename.endswith(".yaml"):
tron_client = client.Client(args.server)
jobs_status = tron_client.jobs()
is_migration_safe = True
with open(filename) as f:
jobs = yaml.load(f)["jobs"]
job_names = [job["name"] for job in jobs]
if args.job is not None: # only want to migrate specific job
# Overwrite existing jobs since only migrating one job
jobs = [job for job in jobs if job["name"] == args.job]
if not jobs:
raise ValueError(f"Invalid job specified. Options were {job_names}")
job_name_with_ns = args.old_ns + "." + args.job
is_migration_safe = is_migration_safe & check_job_if_running(jobs_status, job_name_with_ns)
else: # Migrate all jobs in namespace
for job_name in job_names:
job_name_with_ns = args.old_ns + "." + job_name
is_migration_safe = is_migration_safe & check_job_if_running(jobs_status, job_name_with_ns)
if is_migration_safe is True:
print(bcolors.OKBLUE + "Jobs are not running." + bcolors.ENDC)
else:
print(bcolors.WARNING + "Some jobs are still running, abort this migration," + bcolors.ENDC)
return
# try stop cron
ssh_command(hostname, "sudo service cron stop")
# wait unitil yelpsoa-configs branch is merged
res = input("Merge and push yelpsoa-configs branch. Ready to continue? [y/n]")
if res == "y":
# wait for 10 seconds after pushing the branch
time.sleep(30)
# rsyn yelpsoa-configs
command = "sudo rsync -a --delay-updates --contimeout=10 --timeout=10 --chmod=Du+rwx,go+rx --port=8731 --delete yelpsoa-slave.local.yelpcorp.com::yelpsoa-configs /nail/etc/services"
ssh_command(hostname, command)
# migrate jobs to new namespace
command_jobs("move", jobs, args)
# update new namespace
ssh_command(hostname, "sudo paasta_setup_tron_namespace " + args.new_ns)
# update old namespace if only one job is moving
if args.job:
ssh_command(hostname, "sudo paasta_setup_tron_namespace " + args.old_ns)
# clean up namespace
ssh_command(hostname, "sudo paasta_cleanup_tron_namespaces")
# start cron
ssh_command(hostname, "sudo service cron start")
return
if __name__ == "__main__":
main()
================================================
FILE: contrib/mock_patch_checker.py
================================================
#!/usr/bin/env python3.10
import ast
import sys
class MockChecker(ast.NodeVisitor):
def __init__(self):
self.errors = 0
self.init_module_imports()
def init_module_imports(self):
self.imported_patch = False
self.imported_mock = False
def check_files(self, files):
for file in files:
self.check_file(file)
def check_file(self, filename):
self.current_filename = filename
try:
with open(filename) as fd:
try:
file_ast = ast.parse(fd.read())
except SyntaxError as error:
print("SyntaxError on file %s:%d" % (filename, error.lineno))
return
except OSError:
print("Error opening filename: %s" % filename)
return
self.init_module_imports()
self.visit(file_ast)
def _call_uses_patch(self, node):
try:
return node.func.id == "patch"
except AttributeError:
return False
def _call_uses_mock_patch(self, node):
try:
return node.func.value.id == "mock" and node.func.attr == "patch"
except AttributeError:
return False
def visit_Import(self, node):
if [name for name in node.names if "mock" == name.name]:
self.imported_mock = True
def visit_ImportFrom(self, node):
if node.module == "mock" and (name for name in node.names if "patch" == name.name):
self.imported_patch = True
def visit_Call(self, node):
try:
if (self.imported_patch and self._call_uses_patch(node)) or (
self.imported_mock and self._call_uses_mock_patch(node)
):
if not any([keyword for keyword in node.keywords if keyword.arg == "autospec"]):
print("%s:%d: Found a mock without an autospec!" % (self.current_filename, node.lineno))
self.errors += 1
except AttributeError:
pass
self.generic_visit(node)
def main(filenames):
checker = MockChecker()
checker.check_files(filenames)
if checker.errors == 0:
sys.exit(0)
else:
print("You probably meant to specify 'autospec=True' in these tests.")
print("If you really don't want to, specify 'autospec=None'")
sys.exit(1)
if __name__ == "__main__":
main(sys.argv[1:])
================================================
FILE: contrib/namespace_cleanup.sh
================================================
#/bin/bash
ecosystem="stagef"
read -p "Are you at tron-$ecosystem (y/n)?" RES
echo
if [ $RES = "y" ]; then
#load namespace from _manifest.yaml
for namespace in $(cat /nail/tron/config/_manifest.yaml | uq | jq -r 'keys[]')
do
file=$(cat /nail/tron/config/_manifest.yaml | uq | jq -r .\"$namespace\")
filename=$(basename $file)
if [ -f "/nail/etc/services/tron/$ecosystem/$filename" ]; then
echo "$namespace is up to date"
elif [ $namespace == "MASTER" ]; then
echo "It is MASTER namepsace"
else
num_job=$(cat /nail/tron/config/$filename | uq | jq -r ".jobs | length")
echo "========= $filename ========="
cat /nail/tron/config/$filename
echo "============================="
if [ $num_job == 0 ]; then
echo "$namespace is left behind, deleting the namespace"
tronfig -d $namespace
else
echo "Can't remove the namespace since it is not empty."
fi
fi
done
else
echo "Please change the ecosystem variable in this script or execute this script at tron-$ecosystem"
fi
================================================
FILE: contrib/patch-config-loggers.diff
================================================
--- a/debian/tron/opt/venvs/tron/lib/python3.10/site-packages/kubernetes/client/configuration.py
+++ b/debian/tron/opt/venvs/tron/lib/python3.10/site-packages/kubernetes/client/configuration.py
@@ -71,11 +71,11 @@
"""
_default = None
-
def __init__(self, host="http://localhost",
api_key=None, api_key_prefix=None,
username=None, password=None,
discard_unknown_keys=False,
+ is_logger_used=False,
):
"""Constructor
"""
@@ -106,26 +106,28 @@
"""Password for HTTP basic authentication
"""
self.discard_unknown_keys = discard_unknown_keys
+ self.is_logger_used = is_logger_used
self.logger = {}
- """Logging Settings
- """
- self.logger["package_logger"] = logging.getLogger("client")
- self.logger["urllib3_logger"] = logging.getLogger("urllib3")
- self.logger_format = '%(asctime)s %(levelname)s %(message)s'
- """Log format
- """
- self.logger_stream_handler = None
- """Log stream handler
- """
- self.logger_file_handler = None
- """Log file handler
- """
- self.logger_file = None
- """Debug file location
- """
- self.debug = False
- """Debug switch
- """
+ if self.is_logger_used:
+ """Logging Settings
+ """
+ self.logger["package_logger"] = logging.getLogger("client")
+ self.logger["urllib3_logger"] = logging.getLogger("urllib3")
+ self.logger_format = '%(asctime)s %(levelname)s %(message)s'
+ """Log format
+ """
+ self.logger_stream_handler = None
+ """Log stream handler
+ """
+ self.logger_file_handler = None
+ """Log file handler
+ """
+ self.logger_file = None
+ """Debug file location
+ """
+ self.debug = False
+ """Debug switch
+ """
self.verify_ssl = True
"""SSL/TLS verification
@@ -178,11 +180,12 @@
for k, v in self.__dict__.items():
if k not in ('logger', 'logger_file_handler'):
setattr(result, k, copy.deepcopy(v, memo))
- # shallow copy of loggers
- result.logger = copy.copy(self.logger)
- # use setters to configure loggers
- result.logger_file = self.logger_file
- result.debug = self.debug
+ if self.is_logger_used:
+ # shallow copy of loggers
+ result.logger = copy.copy(self.logger)
+ # use setters to configure loggers
+ result.logger_file = self.logger_file
+ result.debug = self.debug
return result
@classmethod
================================================
FILE: contrib/sync-from-yelp-prod.sh
================================================
#!/bin/bash
rsync --exclude=.stderr --exclude=.stdout -aPv tron-prod:/nail/tron/* example-cluster/
git checkout example-cluster/logging.conf
echo ""
echo "Now Run:"
echo ""
echo " tox -e example-cluster"
echo " ./example-cluster/start.sh"
================================================
FILE: contrib/sync_namespaces_jobs.py
================================================
#!/usr/bin/env python
""" This script is for load testing of Tron
Historically, Tronview and Tronweb were (are) slow. To better understand the performance
bottleneck of Tron, we could use this script to generate the fake namespaces and
jobs as many as we want to perform load testing. Ticket TRON-70 tracks the progress
of speeding up Tronview and Tronweb.
"""
import argparse
import os
from tron import yaml
def parse_args():
parser = argparse.ArgumentParser(
description="Creating namespaces and jobs configuration for load testing",
)
parser.add_argument(
"--multiple",
type=int,
default=1,
help="multiple workload of namespaces and jobs from source directory",
)
parser.add_argument(
"--src",
default="/nail/etc/services/tron/prod",
help="Directory to get Tron configuration files",
)
parser.add_argument(
"--dest",
default="/tmp/tron-servdir",
help="Directory to put Tron configuration files for load testing",
)
args = parser.parse_args()
return args
def main():
args = parse_args()
for filename in os.listdir(args.src):
print(f"filename = {filename}")
filepath = os.path.join(args.src, filename)
if os.path.isfile(filepath) and filepath.endswith(".yaml"):
with open(filepath) as f:
config = yaml.load(f)
if filename == "MASTER.yaml":
for key in list(config):
if key != "jobs":
del config[key]
jobs = config.get("jobs", [])
if jobs is not None:
for job in jobs:
job["node"] = "localhost"
if "monitoring" in job:
del job["monitoring"]
for action in job.get("actions", []):
action["command"] = "sleep 10s"
if "node" in action:
action["node"] = "localhost"
for i in range(args.multiple):
out_filepath = os.path.join(
args.dest,
"load_testing_" + str(i) + "-" + filename,
)
with open(out_filepath, "w") as outf:
yaml.dump(config, outf, default_flow_style=False)
if __name__ == "__main__":
main()
================================================
FILE: debian/changelog
================================================
tron (3.10.0) jammy; urgency=medium
* 3.10.0 tagged with 'make release'
Commit: Merge pull request #1096 from Yelp/u/kkasp/unlearn-how-to-
read-pickles U/kkasp/unlearn how to read pickles
-- Kevin Kaspari <kkasp@yelp.com> Mon, 16 Mar 2026 09:03:19 -0700
tron (3.9.3) jammy; urgency=medium
* 3.9.3 tagged with 'make release'
Commit: Merge pull request #1098 from jhereth/u/jhereth/MLCOMPUTE-
6270/add-attempt-number-label Add k8s label for attempt number
-- Kevin Kaspari <kkasp@yelp.com> Mon, 16 Mar 2026 07:40:42 -0700
tron (3.9.2) jammy; urgency=medium
* 3.9.2 tagged with 'make release'
Commit: Merge pull request #1090 from Yelp/u/kkasp/TRON-2452-
compress-json Compress json
-- Kevin Kaspari <kkasp@yelp.com> Mon, 09 Feb 2026 13:24:43 -0800
tron (3.9.1) jammy; urgency=medium
* 3.9.1 tagged with 'make release'
Commit: Merge pull request #1084 from Yelp/jfong/TRON-2546-fix-spot-
terminatioons-not-ooms TRON-2546: Fix spot termination
identification in current k8s version
-- Jen Patague <jfong@yelp.com> Thu, 08 Jan 2026 09:58:32 -0800
tron (3.9.0) jammy; urgency=medium
* 3.9.0 tagged with 'make release'
Commit: Upgrade Tron to Python 3.10 - TRON-2435 (#1071) * Upgrade
Tron to Python 3.10 * Upgrade zope.interface to a compatible python
3.10 version * Moved moto to requirements dev instead and removed
mock from minimal * lowering object_size for more room * Update
classifier and path in itest
-- Eman Elsabban <emanelsabban@yelp.com> Thu, 18 Dec 2025 06:24:50 -0800
tron (3.8.9) jammy; urgency=medium
* 3.8.9 tagged with 'make release'
Commit: Assume we"ll only see yaml files in logreader.py (#1077) If
someone is using a .yml file - they"ve already gone horribly off-
track :p
-- Luis Perez <luisp@yelp.com> Mon, 24 Nov 2025 13:42:34 -0800
tron (3.8.8) jammy; urgency=medium
* 3.8.8 tagged with 'make release'
Commit: Try to warn folks about incorrect `tronctl publish` usage
(#1076) It"s absurdly easy to use this incorrectly (especially if
you"ve been woken up by a page ;p) - so let"s try to warn folks if
they"re potentially using `tronctl publish` incorrectly afaik, the
usual mistakes here are to use a job/action id (detectable by the
run number) OR to use a too long/short trigger id (either from copy-
pasting too much or too little) I"ve opted to not error out when
this happens since I"m somewhat sure that it"s possible to manually
construct triggers that don"t match this format and depend on those
triggers in soaconfigs. If anyone with more time wants to vibe-code
something to verify this (and maybe even add some validation to the
tronfig schema ;)), then we can always error out immediately
-- Luis Perez <luisp@yelp.com> Thu, 20 Nov 2025 12:01:45 -0800
tron (3.8.7) jammy; urgency=medium
* 3.8.7 tagged with 'make release'
Commit: Lightly refactor skip-and-publish (and add some more output)
(#1075) The current output is pretty minimal and doesn"t help us
(or users) debug particularly efficiently whenever something isn"t
working as expected. Output now looks something like: ``` Skipping
compute-infra-test-service.always_fail.5.fail... ActionRun: compute-
infra-test-service.always_fail.5.fail now in state skipped
Successfully skipped compute-infra-test-service.always_fail.5.fail.
Fetching triggers to publish for compute-infra-test-
service.always_fail.5.fail... Triggers to publish: * compute-
infra-test-service.always_fail.fail.shortdate.2025-11-15 Publishing
trigger compute-infra-test-service.always_fail.fail.shortdate.2025-
11-15... OK ``` I"ve lightly refactored this since I don"t really
know why I inlined all this logic in 2021 and it was bothering me.
-- Luis Perez <luisp@yelp.com> Wed, 12 Nov 2025 06:46:31 -0800
tron (3.8.6) jammy; urgency=medium
* 3.8.6 tagged with 'make release'
Commit: Add another disk eviction substring (#1074) We"re also
seeing messages that look like: `Pod ephemeral local storage usage
exceeds the total limit of containers 1Gi.` which don"t trigger the
existing check. This adds "ephemeral local storage" as another
trigger without removing the existing one. I"m not quite sure how
k8s decides which message to use without reading through the k8s
code further, but it appears that both cases are possible:
https://github.com/kubernetes/kubernetes/blob/350481c4747da5c2ad4f24
e71e7edaabbd4cfe2e/pkg/kubelet/eviction/helpers.go#L53-L57
-- Luis Perez <luisp@yelp.com> Mon, 03 Nov 2025 09:56:04 -0800
tron (3.8.5) jammy; urgency=medium
* 3.8.5 tagged with 'make release'
Commit: TRON-2480: Fix tron systemd unit to retry indefinitely & add
minor delay between restarts (#1070) We saw in
https://yelp.slack.com/archives/CA53K7S68/p1755111528654579 and
https://yelp.slack.com/archives/CA53K7S68/p1752625385958589?thread_t
s=1752624525.373959&cid=CA53K7S68 my change from #1066 to add the
`ExecStartPre` , combined with the default `RestartSec=0` and
`StartLimitBurst=5` meant that tron in a cluster that required some
time to perform the shutdown process would still see `trond` still
running and immediately run through the 5 allowed attempts, then
fail to restart unless retriggered by a timer or socket: > Note
that units which are configured for Restart=, and which reach the
start limit are not attempted to be restarted anymore; however, they
may still be restarted manually or from a timer or socket at a later
point, after the interval has passed. This PR now disables the
restart limits entirely by setting both `StartLimitBurst` and
`StartLimitIntervalSec` to 0, as per the docs: > interval is a time
span with the default unit of seconds, but other units may be
specified, see
[systemd.time(7)](https://www.freedesktop.org/software/systemd/man/l
atest/systemd.time.html#). The special value "infinity" can be used
to limit the total number of start attempts, even if they happen at
large time intervals. Defaults to DefaultStartLimitIntervalSec= in
manager configuration file, and may be set to 0 to disable any kind
of rate limiting. (Note this indicates only setting
`StartLimitIntervalSec=0` is necessary to disable the rate limiting,
but chatgpt convinced me it makes it clearer to the reader if both
are set to 0, happy to undo this if we think we"ll be confused
later) These settings seem to work on tron-infrastage after
modifying it to cause an artificial 60s delay when shutting down, as
we can see restarts are delayed 10s between the next attempt, and
eventually tron is able to start cleanly on its own with no user
intervention:
https://fluffy.yelpcorp.com/i/qnk5kPRNXsMPRbpLv32KvKDLFk1gl72p.html
-- Luis Perez <luisp@yelp.com> Mon, 18 Aug 2025 09:22:27 -0700
tron (3.8.4) jammy; urgency=medium
* 3.8.4 tagged with 'make release'
Commit: Default sliders to show 50 items (#1067) Defaulting to 10
doesn"t actually save any time since we"ve fetched all the data
anyway. Let"s instead default to 50 since that should should be the
most common run_limit This will make pages longer, but it will be
less confusing to folks when they get alerts for failed/unknown/etc
jobs that are past the visible runs with the previous slider
configuration.
-- Luis Perez <luisp@yelp.com> Wed, 23 Jul 2025 14:10:18 -0700
tron (3.8.3) jammy; urgency=medium
* 3.8.3 tagged with 'make release'
Commit: Merge pull request #1066 from Yelp/jfong/TRON-2340-systemd-
sigterm-handling TRON-2340: Update tron unit file to ensure proper
sigterm handling
-- Jen Patague <jfong@yelp.com> Mon, 14 Jul 2025 13:51:48 -0700
tron (3.8.2) jammy; urgency=medium
* 3.8.2 tagged with 'make release'
Commit: Released 3.8.1 via make release
-- Jen Patague <jfong@yelp.com> Mon, 14 Jul 2025 12:42:31 -0700
tron (3.8.1) jammy; urgency=medium
* 3.8.1 tagged with 'make release'
Commit: Enable disallow_untyped_decorators mypy option (#1064) For
once, a small mypy PR :p There was just a single untyped decorator
and I went ahead and wrote some inline comments "cause I don"t think
I"ll remember how to read this after this gets merged :deepfried-
loljpg:
-- Luis Perez <luisp@yelp.com> Wed, 02 Jul 2025 10:14:27 -0700
tron (3.8.0) jammy; urgency=medium
* 3.8.0 tagged with 'make release'
Commit: Allow transitioning to success/fail from any terminal state
(#1057) This is helpful when folks have handled failures outside of
Tron (or have done something outside of Tron that nominally means
that the Tron status is now incorrect) OR to work-around any
weirdness with Tron states (e.g., something funky happened in k8s
and Tron never saw the event) NOTE: this PR changes a bunch of
extra files - but that"s just due to mypy following more code paths
after I typed the ActionRunController `__init__` so that I could go-
to-def in my editor :p Additionally, kkasp and I have occasionally
been runing into an state where `check-requirements` says a
mismatched version of `cryptography` is installed - I finally got
around to debugging this and realized this stems from our very hacky
extra_requirements_yelp.txt shenanigans: pyopenssl has lower/upper-
bounds on cryptography but, due to the ordering we install things
in, `check-requirements` might run before we"ve installed pyopenssl
and downgraded cryptography (and pass) or after (and fail) The real
changes are confined to
`tron/core/action.py::ActionRun::STATE_MACHINE` (and a now-deleted
ActionRun tests that are no longer valid)
-- Luis Perez <luisp@yelp.com> Mon, 30 Jun 2025 10:16:53 -0700
tron (3.7.3) jammy; urgency=medium
* 3.7.3 tagged with 'make release'
Commit: more gracefully handle errors during backfill monitoring
(#1062)
-- Matteo Piano <mpiano@yelp.com> Thu, 26 Jun 2025 05:54:02 -0700
tron (3.7.2) jammy; urgency=medium
* 3.7.2 tagged with 'make release'
Commit: Merge pull request #1056 from Yelp/u/kkasp/rest-in-peace-
tronweb2 Delete tronweb2
-- Kevin Kaspari <kkasp@yelp.com> Wed, 25 Jun 2025 10:25:34 -0700
tron (3.7.1) jammy; urgency=medium
* 3.7.1 tagged with 'make release'
Commit: Merge pull request #1055 from Yelp/u/kkasp/TRON-2007-tron-
disk-evictions Add disk eviction error code and check logic
-- Kevin Kaspari <kkasp@yelp.com> Fri, 20 Jun 2025 10:11:01 -0700
tron (3.7.0) jammy; urgency=medium
* 3.7.0 tagged with 'make release'
Commit: Save idempotent to json - TRON-2154 (#1051) * Save
idempotent to json * set idempotent to false if it doesnt exist *
address review
-- Eman Elsabban <emanelsabban@yelp.com> Wed, 18 Jun 2025 13:09:02 -0700
tron (3.6.3) jammy; urgency=medium
* 3.6.3 tagged with 'make release'
Commit: ignore cached okta token in backfills (#1054)
-- Matteo Piano <mpiano@yelp.com> Mon, 16 Jun 2025 01:38:02 -0700
tron (3.6.2) jammy; urgency=medium
* 3.6.2 tagged with 'make release'
Commit: cache auth tokens before starting backfill jobs (#1053)
-- Matteo Piano <mpiano@yelp.com> Fri, 13 Jun 2025 01:23:13 -0700
tron (3.6.1) jammy; urgency=medium
* 3.6.1 tagged with 'make release'
Commit: return auth error that clients can parse (#1052)
-- Matteo Piano <mpiano@yelp.com> Mon, 09 Jun 2025 05:24:25 -0700
tron (3.6.0) jammy; urgency=medium
* 3.6.0 tagged with 'make release'
Commit: Merge pull request #1046 from Yelp/u/kkasp/TRON-2391-
aggregate-metrics U/kkasp/tron 2391 aggregate metrics
-- Kevin Kaspari <kkasp@yelp.com> Wed, 04 Jun 2025 10:43:44 -0700
tron (3.5.2) jammy; urgency=medium
* 3.5.2 tagged with 'make release'
Commit: use oidc token method from vault-tools (#1050)
-- Matteo Piano <mpiano@yelp.com> Wed, 28 May 2025 07:36:00 -0700
tron (3.5.1) jammy; urgency=medium
* 3.5.1 tagged with 'make release'
Commit: fix some annoying warnings (#1049)
-- Matteo Piano <mpiano@yelp.com> Tue, 27 May 2025 10:22:44 -0700
tron (3.5.0) jammy; urgency=medium
* 3.5.0 tagged with 'make release'
Commit: add support for api auth via vault (#1048) add support for
api auth via vault
-- Matteo Piano <mpiano@yelp.com> Tue, 27 May 2025 08:47:48 -0700
tron (3.4.10) jammy; urgency=medium
* 3.4.10 tagged with 'make release'
Commit: Merge pull request #1045 from Yelp/u/kkasp/TRON-2414-fix-
broken-config-parse U/kkasp/tron 2414 fix broken config parse
-- Kevin Kaspari <kkasp@yelp.com> Thu, 08 May 2025 09:51:28 -0700
tron (3.4.9) jammy; urgency=medium
* 3.4.9 tagged with 'make release'
Commit: Merge pull request #1043 from Yelp/u/kkasp/TRON-2414-set-
extra-safe-transaction-limit Drop under the limit a bit more for
maximum safety
-- Kevin Kaspari <kkasp@yelp.com> Thu, 01 May 2025 10:54:54 -0700
tron (3.4.8) jammy; urgency=medium
* 3.4.8 tagged with 'make release'
Commit: fix build_url_request when method is None (#1041)
-- Luis Perez <luisp@yelp.com> Mon, 14 Apr 2025 10:52:51 -0700
tron (3.4.7) jammy; urgency=medium
* 3.4.7 tagged with 'make release'
Commit: Merge pull request #1042 from Yelp/u/kkasp/DAR-2637-lower-
max-transact-items Reduce transact size to avoid cap
-- Kevin Kaspari <kkasp@yelp.com> Thu, 10 Apr 2025 08:24:26 -0700
tron (3.4.6) jammy; urgency=medium
* 3.4.6 tagged with 'make release'
Commit: Merge pull request #1039 from Yelp/u/kkasp/KKASP-0001-
download-more-time Upgrade moment and get the latest tz info
-- Kevin Kaspari <kkasp@yelp.com> Mon, 07 Apr 2025 11:10:20 -0700
tron (3.4.5) jammy; urgency=medium
* 3.4.5 tagged with 'make release'
Commit: Bump task_processing from 1.3.4 to 1.3.5 (#1040) I made a
silly mistake and didn"t increase the attempt counter
-- Luis Perez <luisp@yelp.com> Thu, 03 Apr 2025 15:37:22 -0700
tron (3.4.4) jammy; urgency=medium
* 3.4.4 tagged with 'make release'
Commit: Update task_processing to 1.3.4 for watch backoff (#1038)
This includes https://github.com/Yelp/task_processing/pull/225,
which should add some backoff to watch restarts to avoid slamming
the apiserver
-- Luis Perez <luisp@yelp.com> Thu, 03 Apr 2025 14:01:31 -0700
tron (3.4.3) jammy; urgency=medium
* 3.4.3 tagged with 'make release'
Commit: Bump kubernetes clientlib to the latest supported version
(#1037) See https://github.com/kubernetes-client/python?tab=readme-
ov-file#compatibility
-- Luis Perez <luisp@yelp.com> Thu, 03 Apr 2025 10:46:44 -0700
tron (3.4.2) jammy; urgency=medium
* 3.4.2 tagged with 'make release'
Commit: Merge pull request #1036 from Yelp/u/kkasp/TRON-2396-lower-
min-zoom-for-big-ol-charts Halve minZoom for some of our big charts
-- Kevin Kaspari <kkasp@yelp.com> Thu, 27 Mar 2025 10:42:14 -0700
tron (3.4.1) jammy; urgency=medium
* 3.4.1 tagged with 'make release'
Commit: Bump task_processing to v1.3.3 for Watch restart fix (#1035)
This brings in https://github.com/Yelp/task_processing/pull/223,
which should ensure that we don"t get stuck in a funky restart loop
if k8s tells us our watch"s resourceVersion is too old
-- Luis Perez <luisp@yelp.com> Wed, 26 Mar 2025 11:46:03 -0700
tron (3.4.0) jammy; urgency=medium
* 3.4.0 tagged with 'make release'
Commit: Merge pull request #1032 from Yelp/u/kkasp/TRON-2370-do-ya-
like-dags U/kkasp/tron 2370 do ya like dags
-- Kevin Kaspari <kkasp@yelp.com> Fri, 21 Mar 2025 13:17:02 -0700
tron (3.3.2) jammy; urgency=medium
* 3.3.2 tagged with 'make release'
Commit: Merge pull request #1034 from Yelp/u/mpiano/SEC-
19862_fix_service_param fix service name extraction logic
-- Kevin Kaspari <kkasp@yelp.com> Fri, 21 Mar 2025 11:28:33 -0700
tron (3.3.1) jammy; urgency=medium
* 3.3.1 tagged with 'make release'
Commit: Merge pull request #1033 from Yelp/u/mpiano/SEC-19862_fix
fix auth middleware integration
-- Kevin Kaspari <kkasp@yelp.com> Mon, 17 Mar 2025 12:47:36 -0700
tron (3.3.0) jammy; urgency=medium
* 3.3.0 tagged with 'make release'
Commit: Merge pull request #1005 from Yelp/u/mpiano/SEC-19555 auth
support for Tron APIs
-- Kevin Kaspari <kkasp@yelp.com> Thu, 13 Mar 2025 11:30:42 -0700
tron (3.2.12) jammy; urgency=medium
* 3.2.12 tagged with 'make release'
Commit: Merge pull request #1030 from Yelp/jfong/TRON-1797-tronweb-
path TRON-1797: Put tronweb in a python-version-agnostic location
-- Jen Patague <jfong@yelp.com> Mon, 03 Mar 2025 12:15:00 -0800
tron (3.2.11) jammy; urgency=medium
* 3.2.11 tagged with 'make release'
Commit: Try to load config_name_mapping from disk just once (#1013)
There"s enough files (and enough YAML in these files) that the
IO/YAML parsing takes a significant amount of time. While it"s nice
to always load from the source-of-truth (i.e., the files on-disk) -
it"s not worth paying the performance penalty (especially at the
scale we"re seeing internally) for a negligible benefit. Locally
(with a large test config), this results in a ~5x improvement in
timings. More concretely, my test configs were taking ~30ish seconds
*without* this diff and ~6ish seconds *with* this diff.
-- Luis Perez <luisp@yelp.com> Mon, 24 Feb 2025 09:08:41 -0800
tron (3.2.10) jammy; urgency=medium
* 3.2.10 tagged with 'make release'
Commit: Merge pull request #1028 from Yelp/jfong/TRON-2333 TRON-
2333: Bump task_processing for pod truncation fix
-- Jen Patague <jfong@yelp.com> Fri, 21 Feb 2025 11:08:55 -0800
tron (3.2.9) jammy; urgency=medium
* 3.2.9 tagged with 'make release'
Commit: Merge pull request #1023 from Yelp/u/kkasp/TRON-2342-
exponential-backoff-dynamo-get Add dynamodb retry config for
throttling and other errors. Add exponential backoff and jitter for
unprocessed keys. Fix edge case where we succesfully process keys on
our last attempt but still fail
-- Kevin Kaspari <kkasp@yelp.com> Wed, 12 Feb 2025 13:03:36 -0800
tron (3.2.8) jammy; urgency=medium
* 3.2.8 tagged with 'make release'
Commit: Merge pull request #1025 from Yelp/u/kkasp/DAR-2558-fix-
overstep Fix loop boundary on getting partitions
-- Kevin Kaspari <kkasp@yelp.com> Thu, 30 Jan 2025 11:59:51 -0800
tron (3.2.7) jammy; urgency=medium
* 3.2.7 tagged with 'make release'
Commit: Merge pull request #1027 from Yelp/u/emanelsabban/TRON-2354
Handling timezone aware jobs
-- Eman Elsabban <emanelsabban@yelp.com> Fri, 24 Jan 2025 12:38:21 -0800
tron (3.2.6) jammy; urgency=medium
* 3.2.6 tagged with 'make release'
Commit: Add default behaviour for jobs that dont have some keys and
handle the non-existent of some json_vals (#1017) * Add default
behaviour for jobs that dont have some keys and handle the non-
existent of some json_vals * Remove get from command * cap add and
drop should have values * removing the try/except since it was
added in a separate pr * maybe not all gets are necessary * Adding
comments
-- Eman Elsabban <emanelsabban@yelp.com> Fri, 17 Jan 2025 11:47:48 -0800
tron (3.2.5) jammy; urgency=medium
* 3.2.5 tagged with 'make release'
Commit: Merge pull request #1026 from Yelp/u/kkasp/fix-timezones
Use localize instead of replace when writing tz info
-- Kevin Kaspari <kkasp@yelp.com> Fri, 17 Jan 2025 11:00:55 -0800
tron (3.2.4) jammy; urgency=medium
* 3.2.4 tagged with 'make release'
Commit: Merge pull request #1024 from Yelp/u/kkasp/empty-val Add
check for empty val. Merge json correctly
-- Kevin Kaspari <kkasp@yelp.com> Thu, 16 Jan 2025 08:49:56 -0800
tron (3.2.3) jammy; urgency=medium
* 3.2.3 tagged with 'make release'
Commit: Merge pull request #1016 from Yelp/u/kkasp/TRON-2239-migrate-
pickle-only-state-to-JSON U/kkasp/tron 2239 migrate pickle only
state to json
-- Kevin Kaspari <kkasp@yelp.com> Tue, 14 Jan 2025 12:05:21 -0800
tron (3.2.2) jammy; urgency=medium
* 3.2.2 tagged with 'make release'
Commit: Merge pull request #1014 from Yelp/u/kkasp/fix-tooltip-lol-
its-bootstrap-2.3.1 Disable the tooltip animation that is causing a
strange problem where you can"t get a tooltip when entering from the
top of an object
-- Kevin Kaspari <kkasp@yelp.com> Mon, 13 Jan 2025 06:59:56 -0800
tron (3.2.1) jammy; urgency=medium
* 3.2.1 tagged with 'make release'
Commit: Merge pull request #1022 from Yelp/u/kkasp/pass-json-back-to-
save-queue Pass json_val back to the save queue on failure
-- Kevin Kaspari <kkasp@yelp.com> Fri, 10 Jan 2025 07:27:17 -0800
tron (3.2.0) jammy; urgency=medium
* 3.2.0 tagged with 'make release'
Commit: Merge pull request #1018 from Yelp/u/kkasp/update-delete-
item Update delete_item logic to handle json partitions
-- Kevin Kaspari <kkasp@10-40-19-131-uswest1cdevc.dev.yelpcorp.com> Thu, 09 Jan 2025 12:29:29 -0800
tron (3.1.2) jammy; urgency=medium
* 3.1.2 tagged with 'make release'
Commit: Bump task_processing to v1.3.1 for capability fix (#1020)
Just like Yelp/paasta#3972 and Yelp/paasta#3973, we need to ensure
that there are no duplicates between cap_add and cap_drop -
otherwise, the cap_drop entry will "win" and the duplicate
capability will not be added.
-- Luis Perez <luisp@yelp.com> Thu, 09 Jan 2025 09:21:33 -0800
tron (3.1.1) jammy; urgency=medium
* 3.1.1 tagged with 'make release'
Commit: Merge pull request #1019 from Yelp/u/emanelsabban/capture-
json_val Capturing exception when json_val doesnt exist
-- Eman Elsabban <emanelsabban@yelp.com> Wed, 08 Jan 2025 13:04:07 -0800
tron (3.1.0) jammy; urgency=medium
* 3.1.0 tagged with 'make release'
Commit: Add read_json to be a part of master.yaml config (#1015) *
Add read_json to be a part of master.yaml config * Fix the mypy
error & other failed tests * Addressing reviews * Add reas_json to
restore in shelve function
-- Eman Elsabban <emanelsabban@yelp.com> Thu, 02 Jan 2025 12:51:55 -0800
tron (3.0.0) jammy; urgency=medium
* 3.0.0 tagged with 'make release'
Commit: [TRON-2238] Reading from JSON to restore jobs" state instead
of pickles (#1010) * Reading from Json to restore jobs" state
instead of pickles * Fixing some bugs through testing * Deleting
some comments * mocking get_config_watcher * Try mocking one more
time * Toggling off read_json since we want to merge that way *
Removing some comments * Addressed reviews * Toggling read_json
back off * Addressing more reviews * one more review plz *
includes reviews except tz
-- Eman Elsabban <emanelsabban@yelp.com> Mon, 23 Dec 2024 07:56:01 -0800
tron (2.8.1) jammy; urgency=medium
* 2.8.1 tagged with 'make release'
Commit: Merge pull request #1004 from Yelp/u/kkasp/TRON-2237-
timedeltas-cant-json Use total_seconds for timedeltas. Log job and
jobrun names/runnums on serialization
-- Kevin Kaspari <kkasp@yelp.com> Thu, 31 Oct 2024 09:11:35 -0700
tron (2.8.0) jammy; urgency=medium
* 2.8.0 tagged with 'make release'
Commit: Merge pull request #997 from Yelp/u/kkasp/TRON-2237-write-
json-state Write JSON state
-- Kevin Kaspari <kkasp@yelp.com> Tue, 29 Oct 2024 14:14:38 -0700
tron (2.7.0) jammy; urgency=medium
* 2.7.0 tagged with 'make release'
Commit: Merge pull request #1001 from
Yelp/u/cuza/getting_namespace_logs_from_yelpsoa Fixing Tron logs
for jobs using other services images
-- Kevin Kaspari <kkasp@yelp.com> Tue, 29 Oct 2024 13:31:16 -0700
tron (2.6.0) jammy; urgency=medium
* 2.6.0 tagged with 'make release'
Commit: Use logreader rathern than vector-reader (#1002) This CLI
is being renamed, so let"s account for that
-- Luis Perez <luisp@yelp.com> Thu, 24 Oct 2024 09:34:05 -0700
tron (2.5.3) jammy; urgency=medium
* 2.5.3 tagged with 'make release'
Commit: Merge pull request #1000 from Yelp/jfong/TRON-2208-
nonretryable-to-unknown TRON-2208: Update non_retryable_exit_code
behavior to treat as UNKNOWN
-- Jen Patague <jfong@yelp.com> Mon, 30 Sep 2024 14:12:37 -0700
tron (2.5.2) jammy; urgency=medium
* 2.5.2 tagged with 'make release'
Commit: Use vector-reader cli if new logging pipeline is enabled
(#999) Thankfully, this was a pretty easy change - we really only
needed to parametrize the command name being used and the location
selector is now a lot simpler as it"ll always be the superregion
-- Luis Perez <luisp@yelp.com> Mon, 30 Sep 2024 09:32:22 -0700
tron (2.5.1) jammy; urgency=medium
* 2.5.1 tagged with 'make release'
Commit: Merge pull request #998 from Yelp/jfong/TRON-2277-fix-
nonretryable-exit-codes TRON-2277: Pass along
non_retryable_exit_codes to KubernetesCluster objects
-- Jen Patague <jfong@yelp.com> Thu, 26 Sep 2024 10:21:53 -0700
tron (2.5.0) jammy; urgency=medium
* 2.5.0 tagged with 'make release'
Commit: Attempt to batch config loading for deployments (#996)
Right now we make at most 2N calls to the Tron API during config
deployments: N to get the current configs and at most N if all
services have changes. To start, I"d like to reduce this to N by
allowing GET /api/config to return all the configs so that the only
requests needed are POSTs for changed configs. Depending on how
this goes, we can look into batching up the POSTs so that we can
also do that in a single request. In terms of speed, it looks like
loading all the configs from pnw-prod (on my devbox) with this new
behavior takes ~3s - which isn"t great, but there"s a decent bit of
file IO going on here :(
-- Luis Perez <luisp@yelp.com> Tue, 17 Sep 2024 08:25:15 -0700
tron (2.4.2) jammy; urgency=medium
* 2.4.2 tagged with 'make release'
Commit: Merge pull request #995 from Yelp/u/cuza/making-non-
retryable-exit-code-accept-negative-numbers Fix negative value
check for non-retryable exit codes in Kubernetes configuration
-- Dave Cuza <dcuza@yelp.com> Mon, 09 Sep 2024 12:23:49 -0700
tron (2.4.1) jammy; urgency=medium
* 2.4.1 tagged with 'make release'
Commit: Merge pull request #994 from Yelp/StefanoChiodino-patch-1
Update tronweb.less
-- Luis Perez <luisp@yelp.com> Tue, 03 Sep 2024 11:24:45 -0700
tron (2.4.0) jammy; urgency=medium
* 2.4.0 tagged with 'make release'
Commit: TRON-2208: Add toggle in tron config to disable retries on
LOST k8s jobs (#988) Given that "LOST" means Tron has lost track of
a pod it already thought it had started for a job, attempting to
retry/start a replacement can be dangerous for non-idempotent jobs.
In the current state, these will consume retries, but with some of
our EKS migration methods, LOST tasks are more likely. Therefore, we
should have a way to temporarily pause retries on these. ## Related
Issues - TRON-2208: Add toggle in Tron config to disable retries on
LOST k8s jobs
-- Luis Perez <luisp@yelp.com> Wed, 28 Aug 2024 09:19:14 -0700
tron (2.3.0) jammy; urgency=medium
* 2.3.0 tagged with 'make release'
Commit: Merge pull request #989 from Yelp/jfong/TRON-2195-old-
kubeconfig-paths TRON-2195: Support watcher_kubeconfig_paths
-- Jen Patague <jfong@yelp.com> Thu, 11 Jul 2024 14:25:42 -0700
tron (2.2.7) jammy; urgency=medium
* 2.2.7 tagged with 'make release'
Commit: Only show disable warning on tronctl disable (#990) I"m not
sure I was thinking here since this ended up unconditionally
printing the disable warning - but we can chalk this up to an
intentional PR campaign to warn folks and only show the warnings on
tronctl disable from now on :p
-- Luis Perez <luisp@yelp.com> Thu, 11 Jul 2024 11:49:18 -0700
tron (2.2.6) jammy; urgency=medium
* 2.2.6 tagged with 'make release'
Commit: Update scribereader tests (#983)
-- Yaroslav Liakhovskyi <yaro@yelp.com> Fri, 28 Jun 2024 01:41:29 -0700
tron (2.2.5) jammy; urgency=medium
* 2.2.5 tagged with 'make release'
Commit: Update yelp_clog and use datetime range for S3 logs (#979)
-- Yaroslav Liakhovskyi <yaro@yelp.com> Wed, 26 Jun 2024 08:27:10 -0700
tron (2.2.4) jammy; urgency=medium
* 2.2.4 tagged with 'make release'
Commit: Merge pull request #981 from Yelp/revert-980-
u/jfong/revert_to_2.1.1 Revert "Reverts all changes back through
2.1.1 and retains urgent unprocessedkeys fix"
-- Eman Elsabban <emanelsabban@yelp.com> Thu, 20 Jun 2024 14:52:09 -0700
tron (2.2.3) jammy; urgency=medium
* 2.2.3 tagged with 'make release'
Commit: Reverts all changes back through 2.1.1 and retains urgent
unprocessedkeys fix (#980) * Revert "pass around projected SA
configs properly" This reverts commit
12b1bf27e7b9e9f3fd0963f9d073d2552a58115f. * Revert "Merge remote-
tracking branch "origin/u/mpiano/SEC-18955"" This reverts commit
ea6376d72ffdd269e11cb9338d4f0c656bcd6f66, reversing changes made to
4038f1e173aeff932b6e060fc2690f7aa502a85d. * Revert "Use
S3LogsReader with superregion and UTC timezone (#972)" This reverts
commit af73799363549a082eea11f0f98d5c7f4810abe4.
-- Eman Elsabban <emanelsabban@yelp.com> Thu, 20 Jun 2024 10:07:42 -0700
tron (2.2.2) jammy; urgency=medium
* 2.2.2 tagged with 'make release'
Commit: Merge pull request #977 from Yelp/u/jfong/tron_quick_fix
Fix UnprocessedKeys bug when restoring from dynamodb
-- Jen Patague <jfong@yelp.com> Mon, 17 Jun 2024 17:50:59 -0700
tron (2.2.1) jammy; urgency=medium
* 2.2.1 tagged with 'make release'
Commit: Merge pull request #976 from Yelp/u/mpiano/SEC-18955_fix
pass around projected SA configs properly
-- Jen Patague <jfong@yelp.com> Mon, 17 Jun 2024 14:52:24 -0700
tron (2.2.0) jammy; urgency=medium
* 2.2.0 tagged with 'make release'
Commit: Merge remote-tracking branch "origin/u/mpiano/SEC-18955"
-- Matteo Piano <mpiano@yelp.com> Tue, 11 Jun 2024 02:27:25 -0700
tron (2.1.2) jammy; urgency=medium
* 2.1.2 tagged with 'make release'
Commit: Use S3LogsReader with superregion and UTC timezone (#972)
-- Yaroslav Liakhovskyi <yaro@yelp.com> Wed, 05 Jun 2024 02:17:04 -0700
tron (2.1.1) jammy; urgency=medium
* 2.1.1 tagged with 'make release'
Commit: Handling exceptions thrown from threads span by
ThreadPoolExecutor - TRON-2202 (#969) * Handling exceptions thrown
from threads span by ThreadPoolExecutor * Addressing reviews *
Addressing more reviews * Removed Exit code
-- Eman Elsabban <emanelsabban@yelp.com> Tue, 04 Jun 2024 11:24:00 -0700
tron (2.1.0) jammy; urgency=medium
* 2.1.0 tagged with 'make release'
Commit: Revert the Mesos code deletions (#970) This turned out to
be unsafe to to our use of pickles as a serialization format. *
Revert "Use the latest task_proc (#966)" This reverts commit
01003a980854bc25ed2764c880e1fb69db296fb1. * Revert "Delete
remaining Mesos code (#961)" This reverts commit
1f71d0fa406e530ac943f1fcaf312224015f392c. * Revert "Delete Mesos
related exit codes and docker files - TRON-2187 (#959)" This
reverts commit 33ad2a1657aeea61f899380dada42825e137083b. * Revert
"Delete Mesos logging config (#962)" This reverts commit
640362424f1b1b6bb1c959a04b0843ca1e846c10. * Revert "Merge pull
request #953 from Yelp/u/emanelsabban/TRON-2183" This reverts
commit 10353457221d11f2a587c665bae05b16f3cba447, reversing changes
made to e4114088fefaf6a3d3f5be27e5caf41d7c1c9973. * Revert
"Deleting Mesos code from the Master Control Program" This reverts
commit 18f48ee1db23e1e7f91e0e9e7846eb345d171534.
-- Luis Perez <luisp@yelp.com> Mon, 03 Jun 2024 13:33:05 -0700
tron (2.0.0) jammy; urgency=medium
* 2.0.0 tagged with 'make release'
Commit: Use the latest task_proc (#966) There"s no real changes
here other than dropping all the Mesos-related code from task_proc
-- Luis Perez <luisp@yelp.com> Fri, 17 May 2024 13:49:55 -0700
tron (1.32.5) jammy; urgency=medium
* 1.32.5 tagged with 'make release'
Commit: Merge pull request #965 from Yelp/u/emanelsabban/fix-make-
release Remove /docs/source/generated from gitignore file
-- Eman Elsabban <emanelsabban@yelp.com> Fri, 17 May 2024 09:10:54 -0700
tron (1.32.4) jammy; urgency=medium
* 1.32.4 tagged with 'make release'
Commit: Delete Mesos related exit codes and docker files - TRON-2187
(#959) * Delete Mesos related exit codes and docker files * Adding
a try/except for validating extra keys * Testing deleted extra keys
-- Eman Elsabban <emanelsabban@yelp.com> Fri, 17 May 2024 07:51:23 -0700
tron (1.32.3) jammy; urgency=medium
* 1.32.3 tagged with 'make release'
Commit: Automate make release in Tron (#960)
-- Jon Lee <jonlee@yelp.com> Mon, 13 May 2024 15:36:34 -0700
tron (1.32.2) jammy; urgency=medium
* 1.32.2 tagged with 'make release'
Commit: Merge pull request #953 from Yelp/u/emanelsabban/TRON-2183
Delete Mesos code from statemanager - TRON-2183
-- Eman Elsabban <emanelsabban@yelp.com> Mon, 13 May 2024 12:00:06 -0700
tron (1.32.1) jammy; urgency=medium
* 1.32.1 tagged with 'make release'
Commit: Merge pull request #952 from Yelp/u/emanelsabban/TRON-2182
Deleting Mesos code from the Master Control Program - TRON-2182
-- Eman Elsabban <emanelsabban@yelp.com> Mon, 13 May 2024 11:43:05 -0700
tron (1.32.0) jammy; urgency=medium
* 1.32.0 tagged with 'make release'
Commit: Update task_proc to better handle killing tasks (#951)
We've seen that task_proc/k8s will sometimes not correctly send
events for pods that we try to kill ourselves (either because the
pods are already gone or because the event is somehow missing data),
so this task_proc version will send synthetic events when we call
kill() to ensure that tron is in the correct state :)
Co-authored-by: Jen Patague <jfong@yelp.com>
-- Luis Perez <luisp@yelp.com> Thu, 09 May 2024 09:16:24 -0700
tron (1.31.0) jammy; urgency=medium
* 1.31.0 tagged with 'make release'
Commit: Parallelizing execution of restoring in Tron - TRON-2161
(#950) * Parallelizing execution of restoring in Tron * Addressing
reviews and fixing unit tests * Adding sorting for runs state
otherwise runs will be out of order * Addressing more reviews and
adding exception for exceeding max_attempts * Address typing stuff
and timers * Fixing the typing error * fixing incomplete sentence
-- Eman Elsabban <emanelsabban@yelp.com> Wed, 01 May 2024 12:54:10 -0700
tron (1.30.0) jammy; urgency=medium
* 1.30.0 tagged with 'make release'
Commit: Adding yelp_clog S3LogsReader (#949) * Upgrade yelp
scribereader deps * Enable S3LogsReader for action run logs *
Upgrade boto requirements * Upgrade mypy and update type ignores *
Pin more internal requirements
-- Yaroslav Liakhovskyi <yaro@yelp.com> Mon, 29 Apr 2024 04:57:37 -0700
tron (1.29.5) jammy; urgency=medium
* 1.29.5 tagged with 'make release'
Commit: Merge pull request #940 from Yelp/jfong/TRON-1850-starting-
jobs-stuck TRON-1850: Include 'starting' pods in check for stuck jobs
-- Jen Patague <jfong@yelp.com> Tue, 09 Apr 2024 11:37:15 -0700
tron (1.29.4) jammy; urgency=medium
* 1.29.4 tagged with 'make release'
Commit: Adding logs to Tron to indicate start and scheduling times -
TRON-2152 (#948) * Adding logs to Tron to indicate start and
scheduling times * Addressed reviews on the PR * Address reviews
2.0 * Deleting the start_schedule_jobs flag * Making boot_time a
required param * bring back time.time in duration
-- Eman Elsabban <emanelsabban@yelp.com> Mon, 08 Apr 2024 11:15:48 -0700
tron (1.29.3) jammy; urgency=medium
* 1.29.3 tagged with 'make release'
Commit: Add a top-level exception handler (#947) As the comment
says: let's see if adding a top-level handler (that then re-raises)
and catching BaseException will give us more info as to what's
sometimes causing Tron to exit. I've also added the usual base
exception (Exception) just to be extra-safe (h/t to krall for the
idea)
-- Luis Perez <luisp@yelp.com> Wed, 27 Mar 2024 15:00:00 -0700
tron (1.29.2) jammy; urgency=medium
* 1.29.2 tagged with 'make release'
Commit: Merge pull request #946 from Yelp/u/emanelsabban/edit-
messages Editing some of the messages from previous prs
-- Eman Elsabban <emanelsabban@yelp.com> Wed, 20 Mar 2024 08:33:45 -0700
tron (1.29.1) jammy; urgency=medium
* 1.29.1 tagged with 'make release'
Commit: Merge pull request #942 from Yelp/u/kkasp/TRON-1970-escape-
html-tronweb Use Underscores HTML escaped interpolation in template
for log and command outputs
-- Kevin Kaspari <kkasp@yelp.com> Fri, 08 Mar 2024 08:03:14 -0800
tron (1.29.0) jammy; urgency=medium
* 1.29.0 tagged with 'make release'
Commit: Merge pull request #944 from Yelp/u/emanelsabban/TRON-2124-
expose-prom-metrics Adding prometheus endpoint in tron - TRON-2124
-- Eman Elsabban <emanelsabban@yelp.com> Tue, 05 Mar 2024 12:55:14 -0800
tron (1.28.5) jammy; urgency=medium
* 1.28.5 tagged with 'make release'
Commit: Stop keeping old copies of eventbus files (#941) We've
never restored from these 'backups', and as long as we ensure that
the current file points to a fully written file, it's fine to only
keep at most 2 files around: the actual current file and a temporary
'new' file. To ensure that we're not pointing at a half-written
file, we continue using the age-old pattern for atomic file updates:
write to another file and swap a symlink once the write is complete
-- Luis Perez <luisp@yelp.com> Tue, 20 Feb 2024 11:55:45 -0800
tron (1.28.4) jammy; urgency=medium
* 1.28.4 tagged with 'make release'
Commit: Merge pull request #939 from Yelp/u/wilmerrafael/COMPINFRA-
3601_adding_tron_run_number_label Adding tron run id to pod labels
for k8s
-- Wilmer Bandres <wilmerrafael@yelp.com> Thu, 15 Feb 2024 06:43:40 -0800
tron (1.28.3) jammy; urgency=medium
* 1.28.3 tagged with 'make release'
Commit: Merge pull request #938 from Yelp/u/kkasp/TRON-2112-lock-
start Add lock to tron start to mitigate the risk of running
duplicate jobs…
-- Kevin Kaspari <kkasp@yelp.com> Thu, 08 Feb 2024 11:24:39 -0800
tron (1.28.2) jammy; urgency=medium
* 1.28.2 tagged with 'make release'
Commit: Remove unnecessary mocks (#937) This is what I get for
trusting GHA rather than also running the tests internally :) These
mocks are no longer required and are actually causing test failures
internally.
-- Luis Perez <luisp@yelp.com> Thu, 01 Feb 2024 09:10:42 -0800
tron (1.28.1) jammy; urgency=medium
* 1.28.1 tagged with 'make release'
Commit: Downpin yelp-clog (#936) We had bumped this a couple major
versions since we were also bumping scribereader - but we reverted
the scribereader bump before merging the jammy/py38 branch and
forgot to also revert the yelp-clog bump :)
-- Luis Perez <luisp@yelp.com> Thu, 01 Feb 2024 08:51:40 -0800
tron (1.28.0) jammy; urgency=medium
* 1.28.0 tagged with 'make release'
Commit: Upgrading Tron to py3.8 + patching it with the fix (#934) *
Monkeypatch SimpleQueue back to PySimpleQueue We have a hunch that
this is what is causing our pod event loop to have wildly delayed
items * Revert 'Revert python/jammy upgrades (#907)' This reverts
commit 483da5c0fb258b01b8e47912ad034d43554ada7d. * new formatting
* Bump pyyaml * Rm sad test that is not relevant for validation *
added stuff to run tron locally * matching the python version with
whats currently running in infrastage * adding also changelog *
This commit includes some requriements for clog and try/except block
for handle_events * This commit adds the patch fix * Revert
'matching the python version with whats currently running in
infrastage' This reverts commit
1f81a6d4805d742a7a7a28b1d7d8eef39522a896. * Revert 'adding also
changelog' This reverts commit
951fcc8fc31114bde340bad4b82ced0529e03b65. * precommit fixes the
patch * Fixing mypy issues and tests failing * removing return and
adding comment for handling defer being none * addressing wording
* fix InvariantException back to Exception --------- Co-authored-
by: Luis Perez <luisp@yelp.com> Co-authored-by: Vincent Thibault
<vit@yelp.com>
-- Eman Elsabban <emanelsabban@yelp.com> Wed, 31 Jan 2024 09:25:13 -0800
tron (1.27.5) jammy; urgency=medium
* 1.27.5 tagged with 'make release'
Commit: Allow Tron to use more than 10k file descriptors (#923)
There appears to be an fd leak somewhere in tron, we're not in
danger of hitting any host-level limits - so let's update the unit
file to have a bigger limit in the meantime
-- Luis Perez <luisp@yelp.com> Wed, 11 Oct 2023 12:11:22 -0700
tron (1.27.4) jammy; urgency=medium
* 1.27.4 tagged with 'make release'
Commit: Revert 'Link tronweb_url ' (#928) Reverts #911 as it did
not actually result in a clickable link in Slack
-- Luis Perez <luisp@yelp.com> Tue, 10 Oct 2023 12:26:07 -0700
tron (1.27.3) jammy; urgency=medium
* 1.27.3 tagged with 'make release'
Commit: Catch all exceptions in k8s submit_command() (#926) It's
entirely possible that creating a task_processing task (and/or
submitting one) can result in an exception. At the moment, this
results in the affected ActionRun getting stuck in the Starting
state - but this is a lie and means that the normal
monitoring/alerting on failed runs does not kick in.
-- Luis Perez <luisp@yelp.com> Mon, 21 Aug 2023 12:27:26 -0700
tron (1.27.2) jammy; urgency=medium
* 1.27.2 tagged with 'make release'
Commit: Merge pull request #924 from Yelp/u/vit/fix-
configsecretvolume Fix item assignment issue with
ConfigSecretVolume
-- Vincent Thibault <vit@yelp.com> Mon, 14 Aug 2023 13:36:37 -0700
tron (1.27.1) jammy; urgency=medium
* 1.27.1 tagged with 'make release'
Commit: Update to the latest task_proc (#915) This version pulls in
a fix that stops pods from being launched with a null request. This
has been running fine in infrastage where I've verified that Pods
are indeed being launched with the correct metadata I've verified
this as well with unit tests in task_proc :)
-- Luis Perez <luisp@yelp.com> Mon, 10 Jul 2023 08:28:15 -0700
tron (1.27.0) jammy; urgency=medium
* 1.27.0 tagged with 'make release'
Commit: Remove tronweb2 code (#914) This isn't currently being used
and is complicating the internal build process
-- Luis Perez <luisp@yelp.com> Tue, 13 Jun 2023 08:49:02 -0700
tron (1.26.0) jammy; urgency=medium
* 1.26.0 tagged with 'make release'
Commit: Merge pull request #909 from Yelp/u/vit/tron-secret-volume
TRON-1636: Pass secret_volumes to taskproc from kubernetes
-- Vincent Thibault <vit@yelp.com> Mon, 12 Jun 2023 09:03:39 -0700
tron (1.25.1) jammy; urgency=low
* 1.25.1 tagged with 'make release'
Commit: Merge pull request #911 from Yelp/tchen/link-tronweb-url
Link tronweb_url
-- Tianle Chen <tchen@yelp.com> Mon, 05 Jun 2023 09:21:09 -0700
tron (1.25.0) jammy; urgency=medium
* 1.25.0 tagged with 'make release'
Commit: COMPINFRA-2565: enforce an upper limit on backfill
concurrency (#906) Problem ----- The Kubernetes control plane can
be overwhelmed if a high number of concurrent backfills are
executed. We currently set a relatively high default of and enforce
no upper limit at all. Solution ----- * Reduce the default from
to to reduce the baseline pressure of Tron backfill jobs. *
Introduce and enforce a hard limit of concurrent backfills per
tronctl invocation In a future PR, we might want to track the total
count of running backfills per user in Zookeeper but this change
should already safeguard against overwhelming Tron with backfills in
the meantime. Signed-off-by: Max Falk <gfalk@yelp.com>
-- Luis Perez <luisp@10-40-27-179-uswest1cdevc.dev.yelpcorp.com> Thu, 18 May 2023 09:06:24 -0700
tron (1.24.5) jammy; urgency=medium
* 1.24.5 tagged with 'make release'
Commit: Revert python/jammy upgrades (#907) * Revert 'Upgrades
requirements and adds caching on get loggers (#900)' This reverts
commit 0ac2b69d648bb3b915a80637a4f3051e06a16296. * Revert 'Adds
Python 3.8; build for Jammy (#896)' This reverts commit
f7679b9a281d026b4d956c5735875eded5602310.
-- Luis Perez <luisp@10-40-27-179-uswest1cdevc.dev.yelpcorp.com> Wed, 17 May 2023 08:44:16 -0700
tron (1.24.4) jammy; urgency=medium
* 1.24.4 tagged with 'make release'
Commit: Updates date arithmetic to handle whitespace (#903)
-- Jon Lee <jonlee@yelp.com> Thu, 09 Mar 2023 14:23:44 -0800
tron (1.24.3) jammy; urgency=medium
* 1.24.3 tagged with 'make release'
Commit: Upgrades kubernetes version to support 1.21 (#902)
-- Jon Lee <jonlee@yelp.com> Thu, 09 Mar 2023 12:15:55 -0800
tron (1.24.2) jammy; urgency=medium
* 1.24.2 tagged with 'make release'
Commit: Ignores CryptographyDeprecationWarning (#901) * Ignores
CryptographyDeprecationWarning
-- Jon Lee <jonlee@yelp.com> Thu, 09 Mar 2023 11:46:44 -0800
tron (1.24.1) jammy; urgency=medium
* 1.24.1 tagged with 'make release'
Commit: Upgrades requirements and adds caching on get loggers (#900)
* updates axe-core * Upgrade twisted * Stop locking on getting
loggers * Adds better description and commit suggestions *
Upgrades Werkzeug dependency * Upgrades future dependency *
Upgrades ipython dependency * Upgrades cryptography dependency *
Upgrades setuptools dependency * Upgrades certifi dependency *
Upgrades urllib3 dependency * Upgrades rsa dependency * Upgrades
Pygments dependency * Upgrades jinja2 for docs dependency *
Upgrades docs dependencies * Update tron/trondaemon.py Co-authored-
by: Luis Pérez <luisp@yelp.com> --------- Co-authored-by: Luis
Pérez <luisp@yelp.com>
-- Jon Lee <jonlee@yelp.com> Wed, 08 Mar 2023 10:13:38 -0800
tron (1.24.0) jammy; urgency=medium
* 1.24.0 tagged with 'make release'
Commit: Fixes make release for jammy (#899)
-- Jon Lee <jonlee@yelp.com> Fri, 03 Mar 2023 05:39:51 -0800
tron (1.23.10) bionic; urgency=medium
* 1.23.10 tagged with 'make release'
Commit: Merge pull request #890 from
Yelp/u/cuza/logging_tron_exit_status Adding ExecStopPost to systemd
unit file to log tron exit status
-- root <root@ba896c01f138> Tue, 31 Jan 2023 18:27:19 +0000
tron (1.23.9) bionic; urgency=medium
* 1.23.9 tagged with 'make release'
Commit: Merge pull request #887 from Yelp/u/jfong/TRON-1723 TRON-
1723: Add user attribution into user agent when invoking tronctl
commands
-- root <root@35f519810749> Wed, 07 Dec 2022 20:29:42 +0000
tron (1.23.8) bionic; urgency=medium
* 1.23.8 tagged with 'make release'
Commit: TRON-1825: Add additional failure handling of specific
errors (#886) Adds additional failure handling of specific errors
Adds handling of spot interruptions and k8s scaling down Captures
real exit codes from failures.
-- root <root@b5061e28e264> Mon, 05 Dec 2022 15:43:23 +0000
tron (1.23.7) bionic; urgency=medium
* 1.23.7 tagged with 'make release'
Commit: Use correct dict casing for k8s metadata (#885) The data
we'd been dumping into our logging streams was using different key
names than what task_proc was actually sending k8s: we were logging
the python-ified names, but task_proc was sending tron the literal
k8s payloads (i.e., keynames being camelCased). We didn't notice
this 'cause until the initial attempt at working around this weird
k8s bug we weren't actually logging what tron was seeing and our
test data in the unit tests was based on what we'd been seeing in
our logging streams
-- root <root@93f5efd72e85> Wed, 23 Nov 2022 19:44:24 +0000
tron (1.23.6) bionic; urgency=medium
* 1.23.6 tagged with 'make release'
Commit: Detect abnormal successful exits in k8s (#884) this is
kinda wild: we're seeing that a kubelet will sometimes fail to start
a container (usually due to what appear to be race conditions like
those mentioned in
https://github.com/kubernetes/kubernetes/issues/100047#issuecomment-
797624208 and then decide that these Pods should be phase=Succeeded
with an exit code of 0 - even though the container never actually
started. So far, we've noticed that when this happens, the and
fields will be - thus we'll check for at least one of these
conditions to detect an abnormal exit and actually 'fail' the
affected action
-- root <root@4c9236847e02> Tue, 22 Nov 2022 19:28:02 +0000
tron (1.23.5) bionic; urgency=medium
* 1.23.5 tagged with 'make release'
Commit: Merge pull request #882 from Yelp/DAR-1739-revert-rookout
Revert 'This adds rookout to tron (TRON-1764) (#875)'
-- root <root@b023a97c11d6> Wed, 26 Oct 2022 00:24:33 +0000
tron (1.23.4) bionic; urgency=medium
* 1.23.4 tagged with 'make release'
Commit: Bail out earlier on large tron logs (#881) It's possible
for there to be multiple gigabytes of logs in our logging streams
and we don't want Tron sitting there processing these for ages on
end. This isn't a silver bullet, but this should help in the
meantime
-- root <root@d4d7abb7b249> Mon, 24 Oct 2022 16:02:12 +0000
tron (1.23.3) bionic; urgency=medium
* 1.23.3 tagged with 'make release'
Commit: TRON-1806 Adds new function in check_tron_jobs to skip
failed logging queries for a specific superregion (#880) Adds new
function in check_tron_jobs --skip-sensu-failure-logging
-- root <root@277e452fcc16> Fri, 07 Oct 2022 19:53:47 +0000
tron (1.23.2) bionic; urgency=medium
* 1.23.2 tagged with 'make release'
Commit: fixes incorrect test
-- root <root@561dbdc505d9> Thu, 06 Oct 2022 15:24:16 +0000
tron (1.23.1) bionic; urgency=medium
* 1.23.1 tagged with 'make release'
Commit: Merge pull request #877 from Yelp/jammy-3.7 Python 3.7;
build for Jammy
-- root <root@7225e396580b> Thu, 15 Sep 2022 22:42:37 +0000
tron (1.23.0) bionic; urgency=medium
* 1.23.0 tagged with 'make release'
Commit: This adds rookout to tron (TRON-1764) (#875) Adds rookout
to tron (TRON-1764)
-- root <root@fd6a57b542b3> Mon, 12 Sep 2022 19:54:31 +0000
tron (1.22.0) bionic; urgency=medium
* 1.22.0 tagged with 'make release'
Commit: Merge pull request #873 from Yelp/u/emanelsabban/tronUI-1737
Limiting amount of output displayed in Tron UI - TRON-1737
-- root <root@3923dfd1fe65> Tue, 23 Aug 2022 19:35:57 +0000
tron (1.21.0) bionic; urgency=medium
* 1.21.0 tagged with 'make release'
Commit: Merge pull request #874 from Yelp/u/jfong/TRON-1777-update-
taskproc TRON-1777: bump taskproc to get kubeconfig reload fix
-- root <root@6bf33780de09> Mon, 15 Aug 2022 18:29:12 +0000
tron (1.20.0) bionic; urgency=medium
* 1.20.0 tagged with 'make release'
Commit: bumped up taskproc ver pass tron version to tskprc
-- root <root@d63f2c9cda1b> Mon, 25 Jul 2022 20:44:50 +0000
tron (1.19.0) bionic; urgency=medium
* 1.19.0 tagged with 'make release'
Commit: Pass port/field selector envvars to task_proc (#869) we
need this for spark drivers in k8s to work - and without the field
selector env vars we're not able to fully adhere to the paasta
workload contract
-- root <root@9be8d1790a61> Mon, 18 Apr 2022 16:10:56 +0000
tron (1.18.0) bionic; urgency=medium
* 1.18.0 tagged with 'make release'
Commit: Merge pull request #867 from Yelp/u/kawaiwan/retry-honors-
triggers Add arg to for waiting for dependencies
-- root <root@27a2aed6edd5> Wed, 13 Apr 2022 18:41:37 +0000
tron (1.17.1) bionic; urgency=medium
* 1.17.1 tagged with 'make release'
Commit: Create KubernetesActionRuns for executor: spark (#866) For
now, we should be able to just use a KubernetesActionRun for Spark
drivers - worst case, I think we'll just have a couple places where
we branch on if we absolutely need to do something Spark-specific
and can't just pass that down from paasta-tools This PR also
removes spark_driver_service_account_name - I'm not sure what I was
thinking initially - we don't really need anything to distinguish
between the driver and executor SA since the executor SA is
configured by the arguments used to start the driver (and thus we
can just start the driver pod as we normally would by using the
service account payload that we'd use for a normal tron-launched
pod)
-- root <root@46477e094be3> Mon, 21 Mar 2022 15:03:15 +0000
tron (1.17.0) bionic; urgency=medium
* 1.17.0 tagged with 'make release'
Commit: Bump pysensu-yelp to pull in issuetype support (#864)
https://github.com/Yelp/pysensu-yelp/pull/30 was released in pysensu-
yelp==0.4.4 and allows users to set the issuetype for a ticket (so
that sensu-created tickets aren't always of type (the default))
-- root <root@cef92af84f05> Thu, 10 Mar 2022 18:47:54 +0000
tron (1.16.3) bionic; urgency=medium
* 1.16.3 tagged with 'make release'
Commit: Respect ActionRunAdapter max_lines param (#862) Callers can
request a specific number of lines for logs - before this change we
were ignoring that (except for the k8s metadata logs) and always
returning all the data available.
-- root <root@0d7972f57edb> Thu, 10 Feb 2022 22:45:16 +0000
tron (1.16.3) bionic; urgency=medium
* 1.16.3 tagged with 'make release'
Commit: Respect ActionRunAdapter max_lines param (#862) Callers can
request a specific number of lines for logs - before this change we
were ignoring that (except for the k8s metadata logs) and always
returning all the data available.
-- root <root@9dc0edf8a8df> Thu, 10 Feb 2022 19:46:18 +0000
tron (1.16.2) bionic; urgency=medium
* 1.16.2 tagged with 'make release'
Commit: Merge pull request #861 from Yelp/u/kawaiwan/always-restart-
trond Always restart trond if it goes down
-- root <root@1f8824f30d27> Thu, 03 Feb 2022 19:20:28 +0000
tron (1.16.1) xenial; urgency=medium
* 1.16.1 tagged with 'make release'
Commit: Silence yelp_clog.StreamTailer logs + k8s event guard (#855)
This should cleanup any non-fatal exceptions that we see in Tron
logs.
-- root <root@87fe59aafb66> Tue, 07 Dec 2021 19:39:33 +0000
tron (1.16.0) xenial; urgency=medium
* 1.16.0 tagged with 'make release'
Commit: Allow users to use runid for triggers (#853) Some users
have jobs whose output depends on the output of the previous run -
for critical jobs, it's useful to explicitly declare this dependency
so that these jobs never run unless Tron knows that the previous
output is ready/complete (using successful completion as a proxy for
this) For additional context:
https://yelp.slack.com/archives/CA4K8PBLG/p1638402768180500
-- root <root@81bd90063f15> Mon, 06 Dec 2021 19:06:11 +0000
tron (1.15.0) xenial; urgency=medium
* 1.15.0 tagged with 'make release'
Commit: Add Service Account support for k8s jobs (#852) We'll use
this for Pod Identity - there's a webhook that will inject a secret
token + some environment variables if a Pod has a Service Account
set up. paasta-tools will be in charge of creating the Service
Account that we'll use if it doesn't exist (as well as setting up
the annotations on that Service Account).
-- root <root@6959115743ac> Fri, 03 Dec 2021 20:41:48 +0000
tron (1.14.5) xenial; urgency=medium
* 1.14.5 tagged with 'make release'
Commit: Allow passing Pod annotations to task_processing (#850)
We'll need this to toggle certain behaviors (e.g., disable Pods
getting routable IPs internally).
-- root <root@2239f09987e7> Thu, 28 Oct 2021 18:11:55 +0000
tron (1.14.4) xenial; urgency=medium
* 1.14.4 tagged with 'make release'
Commit: Update scribereader to v0.14.1 (#847) v0.14.0 has a bug
that points to the wrong hosts (corpdev uses dev infra, not its own)
-- root <root@b36588a41db7> Wed, 06 Oct 2021 19:44:17 +0000
tron (1.14.3) xenial; urgency=medium
* 1.14.3 tagged with 'make release'
Commit: Upgrade scribereader so that we can read logs in corpdev
(#846) We duplicate the ecosystems that we can point scribereader
at in the package and that list was missing corpdev This causes a
KeyError when trying to get the tailer host:port tuple for tron in
corpdev
-- root <root@f3aeb35abc97> Fri, 01 Oct 2021 19:57:14 +0000
tron (1.14.2) xenial; urgency=medium
* 1.14.2 tagged with 'make release'
Commit: Support passing Pod labels to task_processing (#841) We'll
need this to set labels required by the PaaSTA Workload Contract
(which is needed to ensure that internal tooling will work as
expected with our Pods)
-- root <root@f3474d567429> Fri, 10 Sep 2021 17:32:09 +0000
tron (1.14.1) xenial; urgency=medium
* 1.14.1 tagged with 'make release'
Commit: Show duration in ActionRun history table (#840) This was
missed when this view was initially created and is helpful for users
to determine how run times for a given action are changing over time
at a glance.
-- root <root@5cd3c8fa4dd6> Thu, 02 Sep 2021 20:42:19 +0000
tron (1.14.0) xenial; urgency=medium
* 1.14.0 tagged with 'make release'
Commit: Support node selectors/affinity for k8s tasks (#837) This
additionally adds some error handling when things fail any
invariants for a KubernetesTaskConfig - previously, an
InvariantException meant that we would never realize that a
KubernetesTaskConfig was invalid and that the ActionRun would never
work.
-- root <root@126e6e1cddcf> Thu, 26 Aug 2021 16:00:51 +0000
tron (1.13.2) xenial; urgency=medium
* 1.13.2 tagged with 'make release'
Commit: Use start and end times from ActionRunAttempts (#839) It
turns out that we reset the start time for an ActionRun on any
retries, so let's use the start time from the first attempt and the
end time from the last attempt to figure out what timespan to ask
for logs from scribereader
-- root <root@302b18891663> Tue, 24 Aug 2021 17:55:59 +0000
tron (1.13.1) xenial; urgency=medium
* 1.13.1 tagged with 'make release'
Commit: Merge pull request #836 from Yelp/jfong/TRON-1658-
kubernetesactionrunfromstate TRON-1658: Fix issue restoring
KubernetesActionRuns
-- root <root@ac0cf0844867> Wed, 18 Aug 2021 17:28:33 +0000
tron (1.13.0) xenial; urgency=medium
* 1.13.0 tagged with 'make release'
Commit: Merge pull request #830 from Yelp/u/kawaiwan/automate-
backfills Make tronctl backfill actually run backfills
-- root <root@e0578145385c> Tue, 17 Aug 2021 16:38:44 +0000
tron (1.12.0) xenial; urgency=medium
* 1.12.0 tagged with 'make release'
Commit: Actually kill k8s Pods on KubernetesActionRun::kill() (#828)
We had left this method stubbed out until we implemented kill() in
task_processing, but now we can actually finish implementation here.
-- root <root@1aef58341f12> Mon, 16 Aug 2021 22:03:29 +0000
tron (1.11.0) xenial; urgency=medium
* 1.11.0 tagged with 'make release'
Commit: Support adding/dropping capabilities (#827) We'll need this
for parity with the Mesos implementation and because it's a good
security practice :p
-- root <root@d986f96cb5d1> Tue, 03 Aug 2021 19:32:46 +0000
tron (1.10.3) xenial; urgency=medium
* 1.10.3 tagged with 'make release'
Commit: Merge pull request #824 from Yelp/u/kawaiwan/turn-on-
taskproc-metrics Install yelp-meteorite when building yelp env
-- root <root@63ec31ec3c18> Mon, 02 Aug 2021 20:22:57 +0000
tron (1.10.2) xenial; urgency=medium
* 1.10.2 tagged with 'make release'
Commit: Use un-typo'd failed platform_type for k8s events (#825)
see https://github.com/Yelp/task_processing/pull/173 :p
-- root <root@931eacd3331e> Mon, 02 Aug 2021 18:56:46 +0000
tron (1.10.1) xenial; urgency=medium
* 1.10.1 tagged with 'make release'
Commit: Merge pull request #822 from Yelp/jfong/TRON-1627-
secret_env_to_taskproc TRON-1627: Pass secret_env to taskproc from
kubernetes
-- root <root@e151da5deeea> Wed, 28 Jul 2021 22:43:21 +0000
tron (1.10.0) xenial; urgency=medium
* 1.10.0 tagged with 'make release'
Commit: Enable submitting a task to k8s using task_proc (#818) *
Enable submitting a task to k8s using task_proc We aren't yet
reading any of the events that task_proc is bubbling back up to us,
but that'll come next. With this, we should be giving task_proc all
the information it needs to actually create a usable Pod.
-- root <root@346e4b8d8ad9> Tue, 27 Jul 2021 20:24:40 +0000
tron (1.9.1) xenial; urgency=medium
* 1.9.1 tagged with 'make release'
Commit: Release v1.9.0
-- root <root@b17d2081ca9e> Mon, 26 Jul 2021 19:30:29 +0000
tron (1.8.1) xenial; urgency=medium
* 1.8.1 tagged with 'make release'
Commit: Add black for formatting + some additional linters (#805)
We don't have any automatically enforced formatting (yapf is
optional and not part of our pre-commit), so let's use black since
that seems to be what we've settled on. Additionally, I've added
some other 'standard' pre-commit hooks (as well as reformatted the
pre-commit config file.)
-- root <root@4602d2a09117> Thu, 10 Jun 2021 18:52:48 +0000
tron (1.8.0) xenial; urgency=medium
* 1.8.0 tagged with 'make release'
Commit: Add initial k8s config + global k8s toggle + job opt-out
(#802) We'll be adding two toggles to control Tron's usage of k8s:
* a global killswitch (k8s_options['enabled']) for when we want to
go back to Mesos for an entire cluster (and, in the future, for
when we want to quickly stop all Tronjobs). * a per-job opt-out ()
for any jobs that encounter issues with k8s or that we want to
migrate at a specific time. Since I was adding a k8s config section
to the Tron master config, I also went ahead and added a way to
configure what the k8s API address should be (i.e., the 'master'
address).
-- root <root@74d959c3dc13> Wed, 02 Jun 2021 16:01:28 +0000
tron (1.7.0) xenial; urgency=medium
* 1.7.0 tagged with 'make release'
Commit: Implementation of skip-and-publish (#789) Skipping an
action that has downstream triggers is error-prone as its easy to
forget that you have triggers to emit and what triggers to emit. You
probably need to go check your tronfig definitions to see what
triggers exist and converting the trigger name to a trigger command
can be a little tricky (with date magic). To solve this, we add a
new tronctl command that will skip an action and then publish all
triggers for that action.
-- root <root@ac177ec48467> Thu, 15 Apr 2021 17:15:50 +0000
tron (1.6.1) xenial; urgency=medium
* 1.6.1 tagged with 'make release'
Commit: Merge pull request #780 from Yelp/TRON-1570-remove-old-state
Stop saving command config and fields replaced by command config and
…
-- root <root@413c12b9e90f> Fri, 30 Oct 2020 16:39:41 +0000
tron (1.6.0) xenial; urgency=medium
* 1.6.0 tagged with 'make release'
Commit: Merge pull request #778 from Yelp/TRON-1161-retry-configs
TRON-1161: update configs for retries
-- root <root@d2aa77443876> Wed, 07 Oct 2020 20:23:20 +0000
tron (1.5.1) xenial; urgency=medium
* 1.5.1 tagged with 'make release'
Commit: Merge pull request #777 from Yelp/only-reconfigure-namespace
Only reconfigure jobs in that namespace when a namespace is updated
-- root <root@9dd8ddacff60> Thu, 01 Oct 2020 18:18:18 +0000
tron (1.5.0) xenial; urgency=medium
* 1.5.0 tagged with 'make release'
Commit: Merge pull request #775 from Yelp/TRON-1563-retries-separate
TRON-1563: save state and configs for retries independently
-- root <root@a4d896662a63> Tue, 15 Sep 2020 00:33:05 +0000
tron (1.4.6) xenial; urgency=medium
* 1.4.6 tagged with 'make release'
Commit: Merge pull request #774 from Yelp/drmorr/TRON-
1566/redact_aws_keys redact AWS credentials from the logs
-- root <root@60f4e0ad0a16> Wed, 09 Sep 2020 17:44:42 +0000
tron (1.4.5) xenial; urgency=medium
* 1.4.5 tagged with 'make release'
Commit: Merge pull request #773 from Yelp/TRON-1564-allow-check-oom-
events Skip check_oom_events key from monitoring, which is only
used by paasta
-- root <root@0e092e6866b4> Thu, 03 Sep 2020 17:30:12 +0000
tron (1.4.4) xenial; urgency=medium
* 1.4.4 tagged with 'make release'
Commit: Merge pull request #769 from Yelp/try-react Prototype React
version of tronweb
-- root <root@a921747b1922> Fri, 28 Aug 2020 18:20:16 +0000
tron (1.4.3) xenial; urgency=medium
* 1.4.3 tagged with 'make release'
Commit: Merge pull request #770 from Yelp/TRON-1561-no-overlap-alert-
if-queueing Do not alert for overlapping runs if queueing is
disabled
-- root <root@afcdad7311e7> Wed, 26 Aug 2020 21:02:42 +0000
tron (1.4.2) xenial; urgency=medium
* 1.4.2 tagged with 'make release'
Commit: Merge pull request #765 from Yelp/drmorr/TRON-
1554/fix_pypi_url don't use public pypi for internal builds
-- root <root@ae9f03491631> Tue, 04 Aug 2020 18:23:42 +0000
tron (1.4.1) xenial; urgency=medium
* 1.4.1 tagged with 'make release'
Commit: v1.4.1
-- root <root@f04de09d1fa0> Thu, 30 Jul 2020 23:56:44 +0000
tron (1.4.0) xenial; urgency=medium
* 1.4.0 tagged with 'make release'
Commit: Merge branch 'TRON-1527-separate-job-run-state'
-- root <root@faa832e0502e> Tue, 28 Jul 2020 22:24:08 +0000
tron (1.3.15) xenial; urgency=medium
* 1.3.15 tagged with 'make release'
Commit: Merge pull request #757 from Yelp/dedup-save-queue De-
duplicate items in the DynamoDB save queue
-- root <root@5a7c409e5d89> Thu, 23 Jul 2020 20:01:54 +0000
tron (1.3.14) xenial; urgency=medium
* 1.3.14 tagged with 'make release'
Commit: Merge pull request #756 from Yelp/TRON-1539-dynamo-metrics
Tron 1539 dynamo metrics
-- root <root@07c5254e0dd9> Wed, 01 Jul 2020 21:26:52 +0000
tron (1.3.13) xenial; urgency=medium
* 1.3.13 tagged with 'make release'
Commit: Merge pull request #755 from Yelp/drmorr/COMPINFRA-
333/bump_requirements Bump requirements to pick up new task_proc
version
-- root <root@d26de9c44c56> Wed, 06 May 2020 22:55:55 +0000
tron (1.3.12) xenial; urgency=medium
* 1.3.12 tagged with 'make release'
Commit: Merge pull request #754 from Yelp/u/dpopes/TRON-1531-
keyboard-interactive-suppress-tty-if-no-prompt TRON-1531: Suppress
the need to prompt the user via tty
-- root <root@c1df7d685229> Tue, 05 May 2020 18:26:53 +0000
tron (1.3.11) xenial; urgency=medium
* 1.3.11 tagged with 'make release'
Commit: Merge pull request #753 from Yelp/u/dpopes/SEC-12778-support-
keyboard-interactive-ssh Support keyboard-interactive as an
authentication method for ssh
-- root <root@9879ae11933f> Mon, 27 Apr 2020 18:01:41 +0000
tron (1.3.10) xenial; urgency=medium
* 1.3.10 tagged with 'make release'
Commit: block new saves if save queue is too big
-- root <root@7fe1902868f5> Tue, 14 Apr 2020 16:51:46 +0000
tron (1.3.9) xenial; urgency=medium
* 1.3.9 tagged with 'make release'
Commit: fix tests, fix issue where stopping condition can't be
reached
-- root <root@17ff16d29c37> Tue, 14 Apr 2020 14:46:43 +0000
tron (1.3.8) xenial; urgency=medium
* 1.3.8 tagged with 'make release'
Commit: consume save queue in predefined chunks, count errors
correctly
-- root <root@56162b61acd9> Tue, 14 Apr 2020 14:07:12 +0000
tron (1.3.7) xenial; urgency=medium
* 1.3.7 tagged with 'make release'
Commit: Merge pull request #749 from Yelp/u/maksym/fix-redirect Fix
redirect, comment out stuff in tronrepl
-- root <root@f48cdfb768ba> Wed, 08 Apr 2020 23:17:14 +0000
tron (1.3.6) xenial; urgency=medium
* 1.3.6 tagged with 'make release'
Commit: Merge pull request #745 from Yelp/dependabot/pip/psutil-
5.6.6 Bump psutil from 5.6.3 to 5.6.6
-- root <root@c1e0136e3477> Thu, 02 Apr 2020 23:56:54 +0000
tron (1.3.5) xenial; urgency=medium
* 1.3.5 tagged with 'make release'
Commit: Merge pull request #744 from Yelp/mbehrens-TRON-1144-add-
uptime-version Add tron version and uptime to frontend navbar
-- root <root@d1e49d6d57c9> Mon, 16 Mar 2020 17:38:19 +0000
tron (1.3.4) xenial; urgency=medium
* 1.3.4 tagged with 'make release'
Commit: Merge pull request #741 from Yelp/fix-tz-forward Fix bug
from fall forward last year
-- root <root@2b5268deb6de> Fri, 06 Mar 2020 18:59:59 +0000
tron (1.3.3) xenial; urgency=medium
* 1.3.3 tagged with 'make release'
Commit: Merge pull request #737 from Yelp/u/siruitan/TRON-385-
skip_validate_in_write_config Skip job graph validation in
write_config
-- root <root@8b441532ebab> Thu, 06 Feb 2020 18:59:31 +0000
tron (1.3.2) xenial; urgency=medium
* 1.3.2 tagged with 'make release'
Commit: Merge branch 'drmorr/TRON-
1369/fixing_the_clusterman_invocation'
-- root <root@d12c97f27fb7> Wed, 05 Feb 2020 23:32:42 +0000
tron (1.3.1) xenial; urgency=medium
* 1.3.1 tagged with 'make release'
Commit: Merge pull request #735 from Yelp/drmorr/TRON-
1454/shorten_tron_directory_names tron output dir names shortened
-- root <root@24a5021f338d> Tue, 04 Feb 2020 18:35:32 +0000
tron (1.3.0) xenial; urgency=medium
* 1.3.0 tagged with 'make release'
Commit: Merge branch 'drmorr/TRON-1369/clusterman_env_var'
-- root <root@bd7d68bcdb7a> Thu, 16 Jan 2020 18:59:08 +0000
tron (1.2.5) xenial; urgency=medium
* 1.2.5 tagged with 'make release'
Commit: Merge branch 'u/kawaiwan/bump-task-proc-to-0.1.8'
-- root <root@308ec6e1aa22> Tue, 12 Nov 2019 01:01:46 +0000
tron (1.2.4) xenial; urgency=medium
* 1.2.4 tagged with 'make release'
Commit: Merge pull request #723 from Yelp/drmorr/TRON-
1329/fix_time_interval_construction fix time interval construction
in check_tron_jobs
-- root <root@1a1c533ec7a5> Wed, 06 Nov 2019 21:56:14 +0000
tron (1.2.3) xenial; urgency=medium
* 1.2.3 tagged with 'make release'
Commit: Merge pull request #717 from Yelp/monitoring-backfill-
buckets Try to handle backfills better in monitoring precious runs
-- root <root@9bc878dfcb57> Tue, 15 Oct 2019 23:27:13 +0000
tron (1.2.2) xenial; urgency=medium
* 1.2.2 tagged with 'make release'
Commit: Merge branch 'drmorr/TRON-
1303/action_runner_sets_env_variables'
-- root <root@b45f42581c03> Mon, 14 Oct 2019 19:47:54 +0000
tron (1.2.1) xenial; urgency=medium
* 1.2.1 tagged with 'make release'
Commit: Merge pull request #716 from Yelp/retry-check-state Do not
auto retry action if state is already succeeded
-- root <root@bf4306e0c13c> Wed, 09 Oct 2019 16:57:32 +0000
tron (1.2.0) xenial; urgency=medium
* 1.2.0 tagged with 'make release'
Commit: Merge pull request #715 from Yelp/auto-recovery
Automatically try to recover on unknown ssh actions
-- root <root@2ceaed9bdb6b> Wed, 09 Oct 2019 00:17:59 +0000
tron (1.1.0) xenial; urgency=medium
* 1.1.0 tagged with 'make release'
Commit: Merge pull request #714 from Yelp/recover-command Add
manual recovery command to api
-- root <root@badb29026ca2> Thu, 03 Oct 2019 16:54:12 +0000
tron (1.0.4) xenial; urgency=medium
* 1.0.4 tagged with 'make release'
Commit: Merge pull request #708 from Yelp/recovery-check-finished
Put back check for action runners that have completed in recovery
-- root <root@1a6c525a4bb8> Tue, 24 Sep 2019 00:50:16 +0000
tron (1.0.3) xenial; urgency=medium
* 1.0.3 tagged with 'make release'
Commit: Merge pull request #706 from
Yelp/fix_check_tron_jobs_job_run_ids fix job run ids reported by
check_tron_jobs
-- root <root@9d73659bb267> Thu, 19 Sep 2019 21:56:23 +0000
tron (1.0.2) xenial; urgency=medium
* 1.0.2 tagged with 'make release'
Commit: Don't do a retry_delay when manually retrying a failed
command. (#704)
-- root <root@de1d559b7b81> Wed, 18 Sep 2019 20:28:54 +0000
tron (1.0.1) xenial; urgency=medium
* 1.0.1 tagged with 'make release'
Commit: Merge pull request #692 from Yelp/taskproc_bump Bump
taskproc to handle weird staging offers
-- root <root@f6149bf8cd6c> Wed, 07 Aug 2019 13:37:07 +0000
tron (1.0.0) xenial; urgency=medium
* 1.0.0 tagged with 'make release'
Commit: Released 0.9.14.6 via make release
-- root <root@0be694a64085> Fri, 19 Jul 2019 23:23:34 +0000
tron (0.9.14.6) xenial; urgency=medium
* 0.9.14.6 tagged with 'make release'
Commit: Merge pull request #688 from Yelp/sort_order_fixes Make
string sorting only in ActionRun displaying.
-- root <root@2cdb1ed0c9dc> Tue, 16 Jul 2019 21:46:48 +0000
tron (0.9.14.5) xenial; urgency=medium
* 0.9.14.5 tagged with 'make release'
Commit: Released 0.9.14.4 via make release
-- root <root@aeda6aa81577> Tue, 16 Jul 2019 18:23:28 +0000
tron (0.9.14.4) xenial; urgency=medium
* 0.9.14.4 tagged with 'make release'
Commit: Merge pull request #687 from Yelp/fix_tron_sorting Fix
sorting for DisplayActionRuns when fields are None
-- root <root@73cada4088c5> Tue, 16 Jul 2019 18:21:47 +0000
tron (0.9.14.4) xenial; urgency=medium
* 0.9.14.4 tagged with 'make release'
Commit: Merge pull request #682 from Yelp/stderr_fix Fix stderr
output on check_tron_jobs
-- root <root@88db47311341> Fri, 12 Jul 2019 16:56:55 +0000
tron (0.9.14.3) xenial; urgency=medium
* 0.9.14.3 tagged with 'make release'
Commit: Merge pull request #681 from Yelp/refix-scheduling Use last
run time to get next run time before scheduling
-- root <root@e6eae9e0f565> Thu, 11 Jul 2019 18:11:28 +0000
tron (0.9.14.2) xenial; urgency=medium
* 0.9.14.2 tagged with 'make release'
Commit: Merge pull request #678 from Yelp/ssh-timeouts Improve
logging for deferred errors and apply timeout config to trans…
-- root <root@182fad930a3e> Fri, 05 Jul 2019 20:32:44 +0000
tron (0.9.14.1) xenial; urgency=medium
* 0.9.14.1 tagged with 'make release'
Commit: Merge branch 'master' of github.com:Yelp/Tron
-- root <root@c66730966e5d> Mon, 03 Jun 2019 19:01:33 +0000
tron (0.9.14.0) xenial; urgency=medium
* 0.9.14.0 tagged with 'make release'
Commit: Merge pull request #668 from Yelp/another-waiting-fix Runs
with triggers should start in scheduled state
-- root <root@714976665f09> Thu, 16 May 2019 17:30:06 +0000
tron (0.9.13.4) xenial; urgency=medium
* 0.9.13.4 tagged with 'make release'
Commit: Merge pull request #667 from Yelp/revert-665-revert-654-
u/mingqiz/disable_shelvestore removed mirror store
-- root <root@c5eb8fe59bbf> Tue, 14 May 2019 23:09:44 +0000
tron (0.9.13.3) xenial; urgency=medium
* 0.9.13.3 tagged with 'make release'
Commit: Merge pull request #666 from Yelp/u/kawaiwan/improve-
recovery Make recovery batch script also check if action runner
suddenly goes away
-- root <root@1a4df1f9e377> Tue, 14 May 2019 00:08:31 +0000
tron (0.9.13.2) xenial; urgency=medium
* 0.9.13.2 tagged with 'make release'
Commit: fix guess_realert when next_run is the same as previous_run
(#658) fix guess_realert when next_run is the same as previous_run
-- root <root@b58ae690f313> Thu, 02 May 2019 17:48:01 +0000
tron (0.9.13.1) xenial; urgency=medium
* 0.9.13.1 tagged with 'make release'
Commit: Merge pull request #656 from Yelp/u/mingqiz/fix_dynamodb_bug
Changed dynamodb partition index to int so it is sorted correctly
-- root <root@05c17c2d745e> Tue, 30 Apr 2019 20:05:19 +0000
tron (0.9.13.0) xenial; urgency=medium
* 0.9.13.0 tagged with 'make release'
Commit: Merge pull request #649 from Yelp/drmorr/TRON-
1095/add_duration_to_tronweb duration field added to tronweb
-- root <root@d03d1d3762a0> Mon, 22 Apr 2019 23:16:52 +0000
tron (0.9.12.6) xenial; urgency=medium
* 0.9.12.6 tagged with 'make release'
Commit: Merge pull request #648 from Yelp/u/mingqiz/TRON-1088-bin
Removed interval scheduler
-- root <root@265b3f04ba55> Fri, 19 Apr 2019 18:11:18 +0000
tron (0.9.12.5) xenial; urgency=medium
* 0.9.12.5 tagged with 'make release'
Commit: Merge branch 'drmorr/TRON-605/fix_monitoring_for_stuck_jobs'
-- root <root@546a411b1e3e> Mon, 15 Apr 2019 21:02:28 +0000
tron (0.9.12.4) xenial; urgency=medium
* 0.9.12.4 tagged with 'make release'
Commit: Merge pull request #640 from Yelp/u/mingqiz/TRON-638-
improve_read_speed Improve dynamodb read/write speed
-- root <root@0e05cd00bd1c> Wed, 10 Apr 2019 22:59:47 +0000
tron (0.9.12.3) xenial; urgency=medium
* 0.9.12.3 tagged with 'make release'
Commit: Merge pull request #639 from Yelp/u/mingqiz/TRON-1041-
open_file_limit changed max number of open files to 10000
-- root <root@8634a3efac61> Wed, 03 Apr 2019 00:39:28 +0000
tron (0.9.12.2) xenial; urgency=medium
* 0.9.12.2 tagged with 'make release'
Commit: tron/__init__.py
-- root <root@f0ee26eb2d46> Tue, 02 Apr 2019 18:10:28 +0000
tron (0.9.12.1) xenial; urgency=medium
* 0.9.12.1 tagged with 'make release'
Commit: Merge pull request #631 from Yelp/u/mingqiz/TRON-638-
fix_validation fixed data validation of dynamodb migration
-- root <root@62efe760e39e> Fri, 22 Mar 2019 18:06:11 +0000
tron (0.9.12.0) xenial; urgency=medium
* 0.9.12.0 tagged with 'make release'
Commit: Merge branch 'drmorr/TRON-390/xjob_dep_viz'
-- root <root@778dfeb4d872> Wed, 13 Mar 2019 18:39:40 +0000
tron (0.9.11.1) xenial; urgency=medium
* 0.9.11.1 tagged with 'make release'
Commit: Merge pull request #628 from Yelp/u/mingqiz/TRON-661 Fixed
trusty build
-- root <root@5270842b166b> Tue, 12 Mar 2019 00:32:40 +0000
tron (0.9.11.0) xenial; urgency=medium
* 0.9.11.0 tagged with 'make release'
Commit: Merge pull request #617 from Yelp/u/mingqiz/TRON-638-
migration Migrating from Berkley DB to DynamoDB (TRON-638)
-- root <root@24e1b7483b5b> Fri, 08 Mar 2019 17:27:53 +0000
tron (0.9.10.0) xenial; urgency=medium
* 0.9.10.0 tagged with 'make release'
Commit: Merge pull request #622 from Yelp/waiting-state Waiting
state if an action is waiting for normal or cross-job dependencies
-- root <root@fbc31cafd48e> Mon, 04 Mar 2019 19:48:20 +0000
tron (0.9.9.15) xenial; urgency=medium
* 0.9.9.15 tagged with 'make release'
Commit: Merge pull request #624 from Yelp/add-waiting-state Add
waiting state first for rollback safety
-- root <root@4aecdcf190e2> Mon, 04 Mar 2019 17:53:07 +0000
tron (0.9.9.14) trusty; urgency=medium
* 0.9.9.14 tagged with 'make release'
Commit: Merge pull request #615 from Yelp/fi'-check-job-duration
Ignore duration=None for jobs waiting on e'ternal dependency
-- root <root@0651e12fe496> Fri, 08 Feb 2019 12:31:54 +0000
tron (0.9.9.13) trusty; urgency=medium
* 0.9.9.13 tagged with 'make release'
Commit: fi' disk=none error when restoring from state
-- root <root@347a7c4195b5> Thu, 07 Feb 2019 16:18:18 +0000
tron (0.9.9.12) trusty; urgency=medium
* 0.9.9.12 tagged with 'make release'
Commit: Merge pull request #613 from Yelp/fix-jobrun-state-proxy
Fix inconsistency between JobRun state attribute and is_<state>
checks
-- root <root@a8f427620200> Thu, 07 Feb 2019 15:14:29 +0000
tron (0.9.9.11) trusty; urgency=medium
* 0.9.9.11 tagged with 'make release'
Commit: Merge pull request #610 from Yelp/disk_support Added disk
support to tron on mesos
-- root <root@15e900d9051e> Mon, 04 Feb 2019 18:50:33 +0000
tron (0.9.9.10) trusty; urgency=medium
* 0.9.9.10 tagged with 'make release'
Commit: Merge pull request #611 from Yelp/fix-job-appearing-pending
Fix job appearing pending when waiting on trigger requirement
-- root <root@1158d4960025> Thu, 31 Jan 2019 11:44:45 +0000
tron (0.9.9.9) trusty; urgency=medium
* 0.9.9.9 tagged with 'make release'
Commit: tron.config.schema: use enum types values e'plicitly to fi'
regression after migrating to native enums
-- root <root@721323e97d41> Mon, 07 Jan 2019 13:46:43 +0000
tron (0.9.9.8) trusty; urgency=medium
* 0.9.9.8 tagged with 'make release'
Commit: Merge pull request #603 from Yelp/recovery-none-action-runs
Skip job runs with no action runs during recovery
-- root <root@59681c79eb69> Thu, 20 Dec 2018 19:19:02 +0000
tron (0.9.9.7) trusty; urgency=medium
* 0.9.9.7 tagged with 'make release'
* Fix type bug in creating tasks during recovery
* Only recover Mesos actions with no end time
-- root <root@c190ab3d065f> Tue, 18 Dec 2018 19:27:22 +0000
tron (0.9.9.6) trusty; urgency=medium
* 0.9.9.6 tagged with 'make release'
* Fixes for inactive framework
-- root <root@1ade25b89bcb> Thu, 06 Dec 2018 00:59:04 +0000
tron (0.9.9.5) trusty; urgency=medium
* 0.9.9.5 tagged with 'make release'
* Allow passing extra options to systemd-based distros.
* Update end times for actions
* Fix bug related to Mesos offer timeouts
* Do not reschedule disabled job if it is reconfigured
-- root <root@ca07d1ca6c45> Tue, 04 Dec 2018 21:38:20 +0000
tron (0.9.9.4) trusty; urgency=medium
* 0.9.9.4 tagged with 'make release'
- Fix signal handling so that Tron gracefull shuts down
- Add more information to log lines
-- root <root@ec5f977bc63f> Mon, 19 Nov 2018 23:59:43 +0000
tron (0.9.9.3) trusty; urgency=medium
* 0.9.9.3 tagged with 'make release'
Commit: Merge pull request #587 from Yelp/TRON-536 Removed spaces
in action run html
-- root <root@df98fb91b710> Thu, 15 Nov 2018 00:20:45 +0000
tron (0.9.9.2) trusty; urgency=medium
* 0.9.9.2 tagged with 'make release'
Commit: Merge pull request #583 from Yelp/u/kawaiwan/add-cluster-to-
tron-metrics Add cluster option to metrics script
-- root <root@56ea502bead2> Mon, 12 Nov 2018 18:25:34 +0000
tron (0.9.9.1) trusty; urgency=medium
* 0.9.9.1 tagged with 'make release'
Commit: modify action_id during job migration (#580) * modify
action_id during job migration * pin pre-commit 1.11.2
-- root <root@fe8465f9b037> Tue, 30 Oct 2018 21:42:21 +0000
tron (0.9.9.0) trusty; urgency=medium
* 0.9.9.0 tagged with 'make release'
* Tronctl publish/discard events
* Update DST fall back behavior to be consistent
* Update requirements
* Add script for fetching metrics
-- root <root@0dab49ce8592> Tue, 30 Oct 2018 17:54:04 +0000
tron (0.9.8.4) trusty; urgency=medium
* 0.9.8.4 tagged with 'make release'
Commit: Revert 'Merge pull request #570 from Yelp/pin-requirements'
This reverts commit 33fb19df2d2ec508d254f209c1515bbffabc1523,
reversing changes made to b3c7ab8ae8ffa2f7a08e275175989ea5d8d54a8a.
-- root <root@073ed3171e5d> Fri, 26 Oct 2018 21:36:49 +0000
tron (0.9.8.3) trusty; urgency=medium
* 0.9.8.3 tagged with 'make release'
Commit: Merge pull request #576 from Yelp/yapf-it yapf -rip
-- root <root@ee73a07491c1> Fri, 26 Oct 2018 17:16:09 +0000
tron (0.9.8.2) trusty; urgency=medium
* 0.9.8.2 tagged with 'make release'
Commit: Merge pull request #576 from Yelp/yapf-it yapf -rip
-- root <root@7405d22d2ed3> Fri, 26 Oct 2018 17:14:02 +0000
tron (0.9.8.2) trusty; urgency=medium
* 0.9.8.2 tagged with 'make release'
Commit: Merge pull request #574 from
Yelp/u/chl/rename_all_job_name_after_migration rename all job_name
after migration
-- root <root@0e8e0abfa7bf> Thu, 25 Oct 2018 22:38:54 +0000
tron (0.9.8.1) trusty; urgency=medium
* 0.9.8.1 tagged with 'make release'
Commit: Merge pull request #569 from Yelp/signal-none Don't log
other signals
-- root <root@451d5f0d3ffd> Tue, 23 Oct 2018 23:30:47 +0000
tron (0.9.8.0) trusty; urgency=medium
* 0.9.8.0 tagged with 'make release'
Commit: Merge pull request #566 from Yelp/monitoring-allow-overlap
If runs are allowed to overlap, don't consider that case stuck
-- root <root@7d14a7a2764c> Tue, 23 Oct 2018 20:51:02 +0000
tron (0.9.7.0) trusty; urgency=medium
* 0.9.7.0 tagged with 'make release'
Commit: fix typo in systemd unit file
-- root <root@e8a748ec4fd2> Wed, 17 Oct 2018 17:37:58 +0000
tron (0.9.6.5) trusty; urgency=medium
* 0.9.6.5 tagged with 'make release'
Commit: Merge pull request #561 from Yelp/fix-dependent Fix
actiongraph adapter failing to render dependent actions
-- root <root@473767c09859> Tue, 16 Oct 2018 17:37:45 +0000
tron (0.9.6.4) trusty; urgency=medium
* 0.9.6.4 tagged with 'make release'
Commit: Released 0.9.6.3 via make release
-- root <root@01f20dd7c1de> Mon, 15 Oct 2018 18:27:07 +0000
tron (0.9.6.3) trusty; urgency=medium
* 0.9.6.3 tagged with 'make release'
Commit: Merge pull request #555 from Yelp/u/chl/TRON-
442_create_migrate_job_tool add tronctl move command
-- root <root@ba6f1cb3e4b9> Mon, 15 Oct 2018 17:52:20 +0000
tron (0.9.6.2) trusty; urgency=medium
* 0.9.6.2 tagged with 'make release'
Commit: Merge pull request #548 from Yelp/skip-docs-diagram Skip
state diagram in docs
-- root <root@ee50de3acebd> Tue, 02 Oct 2018 12:23:05 +0000
tron (0.9.6.1) trusty; urgency=medium
* 0.9.6.1 tagged with 'make release'
Commit: fix format string bugs (#538) * fix format string bugs
-- root <root@3b2deac05b19> Fri, 21 Sep 2018 23:46:13 +0000
tron (0.9.6.0) trusty; urgency=medium
* 0.9.6.0 tagged with 'make release'
* Remove percent string support
* Fix bug with fail and retries
* Remove headers from tronfig
* Emit triggers for cross-job dependencies
-- root <root@6267c3201084> Thu, 20 Sep 2018 01:20:15 +0000
tron (0.9.5.1) trusty; urgency=medium
* 0.9.5.1 tagged with 'make release'
* Update taskproc to 0.1.2 for Mesos fixes
* Save jobs when re-configured
* Fix tronweb CSS
* Make scheme optional for Mesos master address
* More feedback on killing Mesos actions
-- root <root@df7a4a1e435e> Mon, 10 Sep 2018 21:14:06 +0000
tron (0.9.5.0) trusty; urgency=medium
* 0.9.5.0 tagged with 'make release'
* Increase upstart timeout
* Remove enableall/disableall from jobs controller
* Deprecate --nodaemon
-- root <root@dd45ed9b4f6d> Wed, 05 Sep 2018 22:04:23 +0000
tron (0.9.4.0) trusty; urgency=medium
* 0.9.4.0 tagged with 'make release'
* add string format support (#490)
* recover Mesos action runs on restart
* run reactor on separate thread
* job trigger configs and eventbus
-- root <root@a3969702bcb5> Tue, 04 Sep 2018 22:23:25 +0000
tron (0.9.3.0) trusty; urgency=medium
* 0.9.3.0 tagged with 'make release'
Commit: make master address optional (#513)
-- root <root@bb6820bc1706> Fri, 24 Aug 2018 22:42:36 +0000
tron (0.9.2.1) trusty; urgency=medium
* 0.9.2.1 tagged with 'make release'
Commit: Merge pull request #508 from Yelp/nix_testify Nix testify
-- root <root@c42f36e81d9b> Wed, 22 Aug 2018 10:53:38 +0000
tron (0.9.2.0) trusty; urgency=medium
* 0.9.2.0 tagged with 'make release'
Commit: catch command rendering type error (#488) * catch command
rendering type error
-- root <root@76f71f6f3016> Thu, 09 Aug 2018 20:46:45 +0000
tron (0.9.1.9) trusty; urgency=medium
* 0.9.1.9 tagged with 'make release'
Commit: Merge pull request #483 from Yelp/retries-delay-kill
Retries delay: kill delayed action correctly
-- root <root@230c51e7feb1> Tue, 24 Jul 2018 11:00:12 +0000
tron (0.9.1.8) trusty; urgency=medium
* 0.9.1.8 tagged with 'make release'
* fix _get_seconds_from_duration bug in monitoring
-- root <root@7cb213fae950> Tue, 10 Jul 2018 20:49:53 +0000
tron (0.9.1.7) trusty; urgency=medium
* 0.9.1.7 tagged with 'make release'
* Make unknown alerts critical instead of warning
* Add manhole for debugging
* Fix validation of full tronfig directory
-- root <root@4a9f80473a39> Mon, 09 Jul 2018 17:35:38 +0000
tron (0.9.1.6) trusty; urgency=medium
* 0.9.1.6 tagged with 'make release'
* Bug fixes
* Remove graceful shutdown
* Mesos: Add default volume configs, implement kill/stop commmands
-- root <root@7406049997a9> Tue, 03 Jul 2018 17:08:51 +0000
tron (0.9.1.5) trusty; urgency=medium
* 0.9.1.5 tagged with 'make release'
Commit: Merge pull request #470 from Yelp/fix-output-dir Check
output dir first
-- root <root@1b6e39a2b125> Mon, 25 Jun 2018 19:27:00 +0000
tron (0.9.1.4) trusty; urgency=medium
* 0.9.1.4 tagged with 'make release'
Commit: Merge pull request #469 from Yelp/u/robj/improve-action-
runner action_runner logs to the output_dir; add timestamps to logs
-- root <root@8d64f3affc91> Mon, 25 Jun 2018 17:00:57 +0000
tron (0.9.1.3) trusty; urgency=medium
* 0.9.1.3 tagged with 'make release'
Commit: Merge pull request #468 from Yelp/u/robj/keep-fs-reasders-
alive handle failures streaming to stdout/stderr
-- root <root@0ab0eb2c4985> Fri, 22 Jun 2018 17:21:54 +0000
tron (0.9.1.2) trusty; urgency=medium
* 0.9.1.2 tagged with 'make release'
Commit: Merge pull request #462 from Yelp/missing-deps add missing
requests and psutil deps
-- root <root@c9cde1a47f3b> Wed, 20 Jun 2018 17:56:19 +0000
tron (0.9.1.1) trusty; urgency=medium
* 0.9.1.1 tagged with 'make release'
Commit: bump version
-- root <root@7f9302ada75f> Fri, 15 Jun 2018 09:34:03 +0000
tron (0.9.1.0) trusty; urgency=medium
* 0.9.1.0 tagged with 'make release'
Commit: Merge pull request #452 from Yelp/mesos-logging Get output
from Mesos tasks
-- root <root@614825dc5b50> Wed, 13 Jun 2018 13:48:43 +0000
tron (0.9.0.0) trusty; urgency=medium
* 0.9.0.0 tagged with 'make release'
Commit: Merge pull request #451 from Yelp/fix-machine-state-during-
recovery set the machine state to running before recovery
-- root <root@7686eebd0261> Tue, 05 Jun 2018 16:48:52 +0000
tron (0.8.0.6) trusty; urgency=medium
* 0.8.0.6 tagged with 'make release'
* Support for expected runtime alerts
* Pre calculate state machine transitions
* Bug fixes
-- root <root@71b346549edd> Wed, 16 May 2018 18:31:23 +0000
tron (0.8.0.5) trusty; urgency=medium
* 0.8.0.5 tagged with 'make release'
Commit: Merge pull request #435 from Yelp/encode-stdout
maybe_encode all data in the file serializer
-- root <root@0ac7a8ef93a0> Tue, 24 Apr 2018 02:46:08 +0000
tron (0.8.0.4) trusty; urgency=medium
* 0.8.0.4 tagged with 'make release'
Commit: friendlier output from tronctl retry
-- root <root@dafe28d81983> Fri, 20 Apr 2018 14:15:05 +0000
tron (0.8.0.3) trusty; urgency=medium
* 0.8.0.3 tagged with 'make release'
Feature: Job actions can now be re-tried using cli command
`tronctl retry <action reference>`. This will automatically
trigger dependent actions upon success of re-tried action.
-- root <root@21bbc7053b21> Thu, 19 Apr 2018 13:14:04 +0000
tron (0.8.0.2) trusty; urgency=medium
* 0.8.0.2 tagged with 'make release'
Fix: regression in tronweb jobs list
-- root <root@aa16172c0160> Wed, 18 Apr 2018 11:09:19 +0000
tron (0.8.0.1) trusty; urgency=medium
* 0.8.0.1 tagged with 'make release'
Commit: Merge pull request #370 from Yelp/python3-deb Python3 deb
-- root <root@ef2489238ddf> Mon, 16 Apr 2018 14:38:29 +0000
tron (0.8.0.0) trusty; urgency=medium
* 0.8.0.0 tagged with 'make release'
Commit: remove duplicate ignore for debian/debhelper-build-stamp
-- root <root@7a84f15cf87d> Wed, 14 Mar 2018 11:14:08 +0000
tron (0.7.8.3) trusty; urgency=medium
* 0.7.8.3 tagged with 'make release'
Commit: Merge pull request #426 from Yelp/maybe-decode-all-the-
things Maybe decode all the things
-- root <root@134c326c0301> Thu, 12 Apr 2018 13:29:50 +0000
tron (0.7.8.2) trusty; urgency=medium
* 0.7.8.2 tagged with 'make release'
Commit: Merge pull request #424 from Yelp/cleanup-retries-validation
Fix validation of cleanup action
-- root <root@bdc822939744> Tue, 10 Apr 2018 11:52:29 +0000
tron (0.7.8.1) trusty; urgency=medium
* 0.7.8.1 tagged with 'make release'
* Retries attribute for action runs
* Preparing for Python 3 upgrade
-- root <root@29a498a76bfe> Fri, 06 Apr 2018 14:45:12 +0000
tron (0.7.8.0) trusty; urgency=medium
* 0.7.8.0 tagged with 'make release'
* Script to clean up namespaces
* Improve check_tron_jobs logging
* Fix bug in date context math with timezones
* Improve tab completion
* Remove more service code
* Use config values to create PaaSTA action run that prints
-- root <root@d2932ccaf8e4> Tue, 03 Apr 2018 18:51:45 +0000
tron (0.7.7.1) trusty; urgency=medium
* 0.7.7.1 tagged with 'make release'
Commit: Preparing 0.7.7.1 release - fix shelve regression - use
bsddb3 directly - remove service functionality from tronweb - add
CORS header - dockerize itests - test debian package in travis - tab
completion improvements
-- root <root@98871b48f7e4> Fri, 23 Mar 2018 21:11:20 +0000
tron (0.7.7.0) trusty; urgency=medium
* 0.7.7.0 tagged with 'make release'
* Cache job names in tab completion
* Remove core service class (services are deprecated now)
* Add backward compatible shelve
* Add initial config fields for actions on PaaSTA
* Bug fixes in tronfig and DST time resolution
-- root <root@bc3b0b62294a> Thu, 22 Mar 2018 18:33:40 +0000
tron (0.7.6.1) trusty; urgency=medium
* 0.7.6.1 tagged with 'make release'
Commit: bump version, fix package building issues
-- root <root@d28ba802797d> Mon, 12 Mar 2018 17:08:34 +0000
tron (0.7.6.0) trusty; urgency=medium
* 0.7.6.0 tagged with 'make release'
Commit: version bump 0.7.6.0
-- root <root@c77afe41973b> Mon, 12 Mar 2018 15:22:58 +0000
tron (0.7.5.3) trusty; urgency=medium
* 0.7.5.3 tagged with 'make release'
Commit: Merge pull request #372 from Yelp/u/jgl/TRON-
212_upgrade_to_argparse Upgrade to argparse
-- root <root@401cb8cd587b> Thu, 08 Mar 2018 00:39:13 +0000
tron (0.7.5.2) trusty; urgency=medium
* 0.7.5.2 tagged with 'make release'
Commit: Merge pull request #373 from Yelp/fix_tz_naive_localization
Only localize datetimes when they lack tzinfo
-- root <root@28c49fd423bf> Fri, 02 Mar 2018 20:49:06 +0000
tron (0.7.5.1) trusty; urgency=medium
* 0.7.5.1 tagged with 'make release'
Commit: Merge pull request #367 from
Yelp/u/jgl/better_pidfile_error_message Make tron pidfile error
message more clear
-- root <root@b5305b0b6d16> Wed, 28 Feb 2018 23:12:22 +0000
tron (0.7.5.0) trusty; urgency=medium
* 0.7.5.0 tagged with 'make release'
Commit: Merge pull request #360 from Yelp/per_job_tz Allow jobs to
override the default timezone
-- root <root@d339239f37b4> Wed, 28 Feb 2018 02:07:09 +0000
tron (0.7.4.2) trusty; urgency=medium
* 0.7.4.2 tagged with 'make release'
Commit: added xenial building support
-- root <root@cd05b3203eb4> Tue, 27 Feb 2018 01:23:33 +0000
tron (0.7.4.1) trusty; urgency=medium
* 0.7.4.1 tagged with 'make release'
Commit: Released 0.7.4.1 via make release
-- root <root@209774aa33a5> Fri, 23 Feb 2018 23:35:28 +0000
tron (0.7.4.0) trusty; urgency=medium
* 0.7.4.0 tagged with 'make release'
* Remove support for mongodb in state serialization
* Remove deprecated restart_interval option for services
* Fix unicode bug in root URL
-- root <root@ed515052fdab> Tue, 13 Feb 2018 20:57:16 +0000
tron (0.7.3.2) trusty; urgency=medium
* 0.7.3.2 tagged with 'make release'
Commit: Merge pull request #347 from Yelp/twisted-twisted Twisted
fix, example cluster and itest improvements
-- root <root@065c430c301e> Fri, 09 Feb 2018 14:39:45 +0000
tron (0.7.3.1) trusty; urgency=medium
* 0.7.3.1 tagged with 'make release'
Commit: Merge branch dont-start-on-boot
-- root <root@4d7566959515> Fri, 09 Feb 2018 09:27:12 +0000
tron (0.7.3.0) trusty; urgency=medium
* $0.7.3.0 tagged with \make release'rCommit: Merge pull request
-- root <root@185112144f8b> Thu, 08 Feb 2018 22:42:17 +0000
tron (0.7.2.0) trusty; urgency=medium
* 0.7.2.0 tagged with make release'
* Use upstart instead of sysv-init
* Added prototype check_tron_jobs and monitoring configs
* Add --delete option for tronfig namespaces
-- root <root@16fb9840b464> Thu, 01 Feb 2018 11:07:08 +0000
tron (0.7.1.0) trusty; urgency=medium
* 0.7.1.0 tagged with 'make release'
Commit: dont assume the USER env var use the more reliable
getpass.getuser() instead of expecting a USER env var to be present.
-- root <root@ac0c082f7689> Tue, 10 Oct 2017 12:47:50 +0000
tron (0.7.0.0) trusty; urgency=medium
* 0.7.0.0 tagged with 'make release'
Commit: fix init.d script
-- root <root@a3aeebf1169f> Fri, 25 Aug 2017 14:22:47 +0000
tron (0.6.2.1) lucid; urgency=low
* Only keep last buffer from ssh connection
-- Federico Giraud <fgiraud@yelp.com> Mon, 15 Aug 2016 10:15:56 -0700
tron (0.6.1.12) lucid; urgency=low
* Fix memory leaks from event recorder and twisted
-- Yejun Yang <yejun@yelp.com> Wed, 06 Jan 2016 18:07:37 -0800
tron (0.6.1.11) lucid; urgency=low
* Add job and service support fields: owner, summary, notes
-- Yejun Yang <yejun@yelp.com> Fri, 02 Oct 2015 11:38:26 -0700
tron (0.6.1.10) lucid; urgency=low
* Optimize tronweb dashboard performance
-- Yejun Yang <yejun@yelp.com> Fri, 19 Dec 2014 13:45:23 -0800
tron (0.6.1.9) lucid; urgency=low
* Log some known exceptions
* Check overlapped run id with instance
-- Yejun Yang <yejun@yelp.com> Thu, 11 Dec 2014 11:54:32 -0800
tron (0.6.1.8) lucid; urgency=low
* Fix service instance restore state, run monitor instead of queue.
-- Yejun Yang <yejun@yelp.com> Tue, 04 Nov 2014 14:14:29 -0800
tron (0.6.1.7) lucid; urgency=low
* Display error message when instance start fail
-- Yejun Yang <yejun@yelp.com> Tue, 04 Nov 2014 10:18:12 -0800
tron (0.6.1.6) lucid; urgency=low
* Ignore service instance start error
* Ignore duplicated run id
-- Yejun Yang <yejun@yelp.com> Mon, 03 Nov 2014 17:21:24 -0800
tron (0.6.1.5) lucid; urgency=low
* Increase channel start timeout
* Fix service monitor restart too soon
-- Yejun Yang <yejun@yelp.com> Thu, 03 Jul 2014 10:28:45 -0700
tron (0.6.1.4) lucid; urgency=low
* Remove incorrectly fixed dead code
* Service monitor task always notify failed instead of down
-- Yejun Yang <yejun@yelp.com> Tue, 01 Apr 2014 10:43:48 -0700
tron (0.6.1.3) lucid; urgency=low
* Fix bug in node service stop
-- Yejun Yang <yejun@yelp.com> Thu, 27 Feb 2014 17:43:57 -0800
tron (0.6.1.2) lucid; urgency=low
* Fix bug prevent reconnection
* Add new config monitor_retries
-- Yejun Yang <yejun@yelp.com> Wed, 05 Feb 2014 10:29:59 -0800
tron (0.6.1) unstable; urgency=low
* tronweb was replaced with a clientside version
* more ssh options are now configurable
* adding an experimental feature to support a max_runtime on jobs
* adding tronctl kill to SIGKILL a service
* add a `--no-header` option to tronfig
-- Daniel Nephin <dnephin@yelp.com> Thu, 02 May 2013 17:34:46 -0700
tron (0.6.0.2) unstable; urgency=low
* Allow serviceinstances to transition from unknown to down
* Better handling for serviceinstance monitor task failing
-- Daniel Nephin <dnephin@yelp.com> Thu, 04 Apr 2013 12:47:14 -0700
tron (0.6.0.1) unstable; urgency=low
* minor visual improvements to tronview
-- Daniel Nephin <dnephin@yelp.com> Tue, 26 Mar 2013 12:22:38 -0700
tron (0.6.0) unstable; urgency=low
* action.requires must be a list (string has been deprecated since 0.3.3)
* tronctl zap has been removed (it shouldn't be necessary anymore)
* service monitoring code has been re-written (services should not longer get stuck in a stopping state)
* hosts can not be validated by specifying a known_hosts file
* additional validation for ssh options and context variables has been moved into configuration validation
* tronview now displays additional details about jobs and services
-- Daniel Nephin <dnephin@yelp.com> Mon, 25 Mar 2013 11:14:13 -0700
tron (0.5.2.3) unstable; urgency=low
* Fix a bug that was preventing nodes from connecting with provided username
* Patched an issue with the SSH connection that could cause exceptions on channel close
-- Daniel Nephin <dnephin@yyelp.com> Fri, 15 Feb 2013 11:19:25 -0800
tron (0.5.2) unstable; urgency=low
* Tron now supports the ability to use different users per node connection.
* Fragmented configuration is now possible by using namespaced config files.
* Additional cleanup and stability patches have been applied.
* State persistence configuration can now be changed without restarting trond
* State saving now includes a namespace, you will need to run `tools/migration/migrate_state.py` to migrate old state.
-- Thomas Robinson <trobinso@yelp.com> Wed, 9 Jan 2013 16:25:53 -0700
tron (0.5.1) unstable; urgency=low
* Jobs which are disabled will no longer be re-enabled when part of their configuration changes.
* Individual actions for a Job can no longer be started independently before a job is started. This was never intentionally supported.
* Adding a new configuration option `allow_overlap` for Jobs, which allows job runs to overlap each other.
* Jobs can now be configured using crontab syntax.
-- Daniel Nephin <dnephin@yyelp.com> Wed, 25 Jul 2012 16:25:53 -0700
tron (0.5.0.2) unstable; urgency=low
* Fix a bug with daemonizing and some versions of twisted reactor.
-- Daniel Nephin <dnephin@yelp.com> Tue, 17 Jul 2012 19:21:39 -0700
tron (0.5.0) unstable; urgency=low
* Names for nodes, jobs, actions and service can now contain underscore characters but are restricted to 255 characters.
* trond now supports a graceful shutdown. Send trond SIGINT to have it wait for all currently running jobs to complete before shutting down. SIGTERM also performs some cleanup before terminating.
* State serialization has changed. See :ref:`config_state` for configuration options. `tools/migration/migrate_state.py` is included to migrate your existing Tron state to a new store. YAML store is now deprecated.
* Old style config, which was deprecated in 0.3 will no longer work.
-- Daniel Nephin <dnephin@yelp.com> Tue, 05 Jun 2012 18:47:34 -0700
tron (0.4.1) unstable; urgency=low
* tronview will once again attempt to find the tty width even when stdout is not a tty.
* Fixed last_success for job context.
* Job runs which are manually cancelled will now continue to schedule new runs.
-- Daniel Nephin <dnephin@yelp.com> Wed, 30 May 2012 16:35:44 -0700
tron (0.4.0) unstable; urgency=low
* Jobs now continue to run all possible actions after one of its actions fail
* Enabling a disabled job now schedules the next run using current time instead of the last successful run (which could cause many runs to be scheduled in the past if the job had been disabled for a while)
* Resolved many inconsistencies and bugs around Job scheduling.
-- Daniel Nephin <dnephin@yelp.com> Fri, 11 May 2012 18:00:00 -0800
tron (0.3.3-1) unstable; urgency=low
* Remove logrotate script from debian packaging
* Add logging.conf to debian packaging
-- James Brown <jbrown@yelp.com> Thu, 19 Apr 2012 14:33:17 -0700
tron (0.3.3) unstable; urgency=low
* Adding a configuration migration script for porting 0.2.x configs to the new 0.3.x
* Remove working_dir from the configuration and replace with output_stream_dir
* Remove logging confiruation from the general config. Logging is now configured using python standaring logging
-- Daniel Nephin <dnephin@yelp.com> Wed, 18 Apr 2012 18:00:00 -0800
tron (0.3.2) unstable; urgency=low
* Fixes a bug when there are multiple node pools
* Adds more unit tests
-- Daniel Nephin <dnephin@yelp.com> Wed, 11 Apr 2012 11:35:05 -0800
tron (0.3.1) unstable; urgency=low
* Bug fix release
* Adding state diagrams to documentation
-- Daniel Nephin <dnephin@yelp.com> Tue, 27 Mar 2012 11:35:05 -0800
tron (0.3.0) unstable; urgency=low
* !Tags, *references, and &anchors are now deprecated in the trond
configuration file. Support will be removed for them in 0.5.
* Adding an enabled option for jobs, so they can be configured as disabled by default
* tron commands (tronview, tronfig, tronctl) now support a global config (defaults to /etc/tron/tron.yaml)
* tronview will now pipe its output through 'less' if appropriate
-- Daniel Nephin <dnephin@yelp.com> Mon, 19 Feb 2012 11:35:05 -0800
tron (0.2.10-1) unstable; urgency=low
* ssh_options is actually optional (sjohnson)
* Cleanup actions no longer cause jobs using an interval scheduler to stop being scheduled if an action fails (sjohnson)
* Failed actions can be skipped, causing dependent actions to run (dnephin)
* Tests have been moved from test/ to tests/ (sjohnson)
* Everything under tron/ web/ and bin/ should now pass pyflakes
-- Daniel Nephin <dnephin@yelp.com> Fri, 17 Feb 2012 11:35:05 -0800
tron (0.2.9-1) unstable; urgency=low
* tronweb works and is documented (mowings-iseatz)
* Daylight Savings Time behavior is more well-defined (sjohnson)
* Jobs that fail after running over their next scheduled time are no longer forgotten (sjohnson)
* Reconfiguring syslog no longer requires restarting trond to take effect (jbrown)
-- Steve Johnson <sjohnson@yelp.com> Mon, 6 Feb 2012 16:26:05 -0800
tron (0.2.8.1-1) unstable; urgency=low
* Set a meaningful Formatter when logging to syslog (jbrown)
* Included prebuilt man pages in distribution so Sphinx isn't required to
have them
-- James Brown <jbrown@yelp.com> Mon, 12 Dec 2011 16:26:05 -0800
tron (0.2.8-1) unstable; urgency=low
* Now on PyPI (irskep)
* New HTML documentation at http://packages.python.org/tron (irskep)
* Cleanup actions: run a command after the success or failure of a job (irskep)
* Logging to syslog with syslog_address config field (irskep)
* "zap" command for services (irskep)
* simplejson is no longer a dependency for Python 2.6 and up (irskep)
* Fix weekday-specified jobs (mon, tues, ...) running a day late (irskep)
* Fix services being allowed in jobs list and causing weird crashes (irskep)
* Fix missing import in www.py (irskep)
* Better resilience to subtlely bad tronfigs (jbrown)
-- Steve Johnson <sjohnson@yelp.com> Fri, 25 Nov 2011 23:27:00 -0400
tron (0.2.7-1) unstable; urgency=low
* Really fix date parsing (rhettg)
* Revert instant service monitor so we wait a while before checking our services (rhettg)
* Clean up some logging (rhettg)
-- Rhett Garber <rhettg@gmail.com> Wed, 14 Sep 2011 16:23:00 -0700
tron (0.2.6-2) unstable; urgency=low
* Fix date parsing
-- James Brown <jbrown@yelp.com> Wed, 14 Sep 2011 15:36:30 -0700
tron (0.2.6-1) unstable; urgency=low
* Support for functional testing. Fixes #49 (irskep)
* Context variables for year, month and day. Fixes #57 (irskep)
* Integrate Google App Engine Cron scheduling syntax. Fixes #71 (irskep)
* Fix crash during service monitoring because of node connect failures. Fixes #77 (rhettg)
* Make action runs explicitly not re-startable. Fixes #78 (rhettg)
* Flush and fsync state file. Fixes #74 (rhettg)
* Handle node disconnect while waiting for channel to start. Fixes #75 (rhettg)
* Replace an aggressive assert with a log message for monitor inconsistency. Fixes #73 (rhettg)
* Handle tronview event listing issue with garbage collected entites. Fixes #70 (rhettg)
* Prevent SSH stampedes by delaying some node EXEC calls (rhettg)
-- Rhett Garber <rhettg@gmail.com> Wed, 14 Sep 2011 14:30:15 -0700
tron (0.2.5-1) unstable; urgency=low
* Introduce event collection system (rhettg)
* Fix a crash in rebuilding all services under certain reconfig scenarios. Fixes #67 (rhettg)
* Fix potential service situation where monitors would stop running after failures (rhettg)
* Additional logging around startup failures (rhettg)
-- Rhett Garber <rhettg@gmail.com> Wed, 22 June 2011 13:24:00 -0800
tron (0.2.4-1) unstable; urgency=low
* Final tronfig fix for stdout/stdin behavior (rhettg)
-- Rhett Garber <rhettg@gmail.com> Tue, 12 Apr 2011 10:50:00 -0800
tron (0.2.3-2) unstable; urgency=low
* Made tronfig work with non-interactive uploads again. (jbrown)
-- James Brown <jbrown@yelp.com> Mon, 11 Apr 2011 22:06:56 -0700
tron (0.2.3-1) unstable; urgency=low
* Resolved an issue where tronfig via stdin wouldn't catch all errors. (rhettg)
* Provided additional config time validation to catch bad configurations. (rhettg)
-- Rhett Garber <rhettg@gmail.com> Thu, 7 Apr 2011 10:50:00 -0800
tron (0.2.2-1) unstable; urgency=low
* Resolved an issue where certain service reconfigurations would
cause the service to be stuck in the DOWN state (rhettg)
* Reworked service to keep consistant instance numbers across restarts
and reconfigs (rhettg)
-- Rhett Garber <rhettg@gmail.com> Wed, 23 Mar 2011 18:26:00 -0800
tron (0.2.1-1) unstable; urgency=low
* Resolve an issue where run_time wasn't set for manually started jobs (rhettg)
* Support for multiple arguments to tronctl (for starting things in bulk) (rhettg)
* Support for starting a job with a specific run_time (rhettg)
* Resolved an issue where services, after a reconfig, wouldn't cause state changes (rhettg)
* Updated man pages (rhettg)
-- Rhett Garber <rhettg@gmail.com> Wed, 09 Feb 2011 15:20:00 -0800
tron (0.2.0-1) unstable; urgency=low
* New services system (rhettg)
-- Rhett Garber <rhettg@gmail.com> Mon, 06 Feb 2011 15:15:00 -0800
tron (0.1.10-1) unstable; urgency=low
* Remove use of deprecated twisted timeout calls. Fixes #9 (rhettg)
* Handle newer versions of twisted (rhettg)
* Dynamic column widths in tronview and better overflow (ebaum)
* Command now displayed in tronview for an action Fixes #32 (ebaum)
* Respect tronview -n option for stdout/stderr output. Fixes #41 (ebaum)
* Show warnings option for tronview. Fixes #46 (ebaum)
* Suppress headers option for tronview. (ebaum)
* Fix an issue where default empty config failed to apply. (rhettg)
* Add versioning to both tron module, command and state file (rhettg)
* Set umask on daemon to allow proper pid-file control (rhettg)
* Fix issue with command context not propogating on live reconfigs. Fixes
#53 (rhettg)
-- Rhett Garber <rhettg@gmail.com> Fri, 14 Jan 2011 13:10:00 -0800
tron (0.1.9-1) unstable; urgency=low
* Fix issue with config changes causing previous job runs to be in an
unstable state. #42 (ebaum)
-- Rhett Garber <rhettg@gmail.com> Mon, 14 Dec 2010 14:12:00 -0800
tron (0.1.8-1) unstable; urgency=low
* Address issue with bad format strings in commands causing untold
disasters. #45 (rhettg)
-- Rhett Garber <rhettg@gmail.com> Mon, 06 Dec 2010 17:38:00 -0800
tron (0.1.7-1) unstable; urgency=low
* Improve log rotation scripts under Debian (jbrown)
* Fix an issue where removing a job with a live reconfig caused the job not to actually be removed. #44 (rhettg)
* Some logging changes to make debugging issues easier (rhettg)
* Some cleanup and better error/delay handling around process control for state writing. (rhettg)
-- Rhett Garber <rhettg@gmail.com> Mon, 22 Nov 2010 15:52:00 -0800
tron (0.1.6-1) unstable; urgency=low
* Fix issue with live reconfigs causing intervals to be skipped (rhettg)
* Added log file re-opening on SIGHUP (fixes #37) (rhettg)
* Fix some issues with cmp functions for jobs that caused incorrect
reconfigs (#38) (mtytel)
* Fix issue with manually starting all_node jobs/services (mtytel)
-- Rhett Garber <rhettg@gmail.com> Fri, 15 Oct 2010 15:05:00 -0700
tron (0.1.5-1) unstable; urgency=low
* Fixed crash due to config bug where SSH options were sometimes missing (rhettg)
* Tweaks to command line interface (rhettg)
-- Rhett Garber <rhettg@gmail.com> Wed, 14 Sep 2010 10:14:00 -0700
tron (0.1.4-1) UNRELEASED; urgency=low
* Simpler default options and config for trond (rhettg)
* Trond daemonizing for proper init.d start/stop behavior (rhettg)
* Fixes to reduce state file writing (matthewtytel)
* Better pre-validation for tronfig (matthewtytel)
* Updates to man pages (matthewtytel)
-- Rhett Garber <rhettg@gmail.com> Tue, 7 Sep 2010 16:51:00 -0700
tron (0.1.3-3) UNRELEASED; urgency=low
* Use /var/lib/tron/ for a working directory (roguelazer)
* Fix bug in Node configuration with services (rhettg)
-- James Brown <roguelazer@gmail.com> Mon, 2 Sep 2010 11:35:00 -0700
tron (0.1.3-2) UNRELEASED; urgency=low
* No longer depend on libyaml
-- James Brown <roguelazer@gmail.com> Mon, 2 Sep 2010 11:00:46 -0700
tron (0.1.3-1) UNRELEASED; urgency=low
* Better debian packaging (roguelazer)
* Cleaner configuration (rhettg)
* SIGHUP handling for reconfiguration (matthewtytel)
* Command Context (environment variables for command execution) (rhettg)
* Show job duration, alphabetize job list and direct stdout/stderr access (matthewtytel)
-- James Brown <roguelazer@gmail.com> Mon, 30 Aug 2010 18:33:00 -0700
tron (0.1.2) UNRELEASED; urgency=low
* Services (matthewtytel)
* Smarter node pools (run all nodes) (matthewtytel)
* Randomized node pool selection (matthewtytel)
-- Rhett Garber <rhettg@gmail.com> Thu, 19 Aug 2010 11:05:00 -0700
tron (0.1.1) UNRELEASED; urgency=low
* On the fly reconfiguration (matthewtytel)
* Saving state (matthewtytel)
* job enable/disable (matthewtytel)
-- Rhett Garber <rhettg@gmail.com> Thu, 19 Aug 2010 11:05:00 -0700
tron (0.1.0) UNRELEASED; urgency=low
* Initial release. (Closes: #XXXXXX)
-- Rhett Garber <rhett@yelp.com> Tue, 23 Mar 2010 07:34:36 -0700
================================================
FILE: debian/compat
================================================
10
================================================
FILE: debian/control
================================================
Source: tron
Section: admin
Priority: optional
Maintainer: Daniel Nephin <dnephin@yelp.com>
Build-Depends: debhelper (>= 7), python3.10-dev, libdb5.3-dev, libyaml-dev, libssl-dev, libffi-dev, dh-virtualenv
Standards-Version: 3.8.3
Package: tron
Architecture: all
Homepage: http://github.com/yelp/Tron
Depends: bsdutils, python3.10, libdb5.3, libyaml-0-2, ${shlibs:Depends}, ${misc:Depends}
Description: Tron is a job scheduling, running and monitoring package.
Designed to replace Cron for complex scheduling and dependencies.
Provides:
Centralized configuration for running jobs across multiple machines
Dependencies on jobs and resources
Monitoring of jobs
================================================
FILE: debian/copyright
================================================
This package was debianized by Steve Johnson <sjohnson@yelp.com>
on Sat, 26 Nov 2011 15:13:00 -0400.
It was downloaded from http://github.com/yelp/Tron
Upstream Author:
Rhett Garber <rhettg@gmail.com>
Matt Tytel <matthewtytel@gmail.com>
Copyright:
Copyright 2010 Yelp
License:
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: debian/docs
================================================
LICENSE.txt
README.md
================================================
FILE: debian/install
================================================
tron/logging.conf var/lib/tron
tronweb/ opt/venvs/tron/
================================================
FILE: debian/pycompat
================================================
2
================================================
FILE: debian/pyversions
================================================
2.5-2.6
================================================
FILE: debian/rules
================================================
#!/usr/bin/make -f
# -*- makefile -*-
DH_VERBOSE := 1
%:
dh $@ --with python-virtualenv
# do not call `make clean` as part of packaging
override_dh_auto_clean:
true
override_dh_auto_build:
true
# do not call `make test` as part of packaging
override_dh_auto_test:
true
override_dh_virtualenv:
echo $(PIP_INDEX_URL)
dh_virtualenv --index-url $(PIP_INDEX_URL) \
--extra-pip-arg --trusted-host=169.254.255.254 \
--extra-pip-arg --only-binary=cryptography \
--python=/usr/bin/python3.10 \
--preinstall cython==0.29.36 \
--preinstall pip==24.3.1 \
--preinstall setuptools==65.5.1
@echo patching k8s client lib for configuration class
patch debian/tron/opt/venvs/tron/lib/python3.10/site-packages/kubernetes/client/configuration.py contrib/patch-config-loggers.diff
override_dh_installinit:
dh_installinit --noscripts
================================================
FILE: debian/tron.conffiles
================================================
/var/lib/tron/logging.conf
================================================
FILE: debian/tron.default
================================================
# Defaults for tron initscript
# sourced by /etc/init.d/tron
# installed at /etc/default/tron by the maintainer scripts
#
# This is a POSIX shell fragment
#
# Additional options that are passed to the Daemon.
DAEMON_OPTS="--log-conf /var/lib/tron/logging.conf"
LISTEN_HOST="0.0.0.0"
LISTEN_PORT="8089"
# User the daemon will run as. Needs to have appropriate credentials to SSH into your working nodes.
# You should take care in setting permissions appropriately for log and working directories on /var
DAEMONUSER=""
# Enable this when you have configured tron to your liking.
RUN="no"
================================================
FILE: debian/tron.dirs
================================================
var/lib/tron/
var/log/tron/
==================
gitextract_3urb6sob/
├── .dockerignore
├── .github/
│ └── workflows/
│ ├── ci.yml
│ └── security-review.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .pyautotest
├── .readthedocs.yaml
├── AGENTS.md
├── CODEOWNERS
├── LICENSE.txt
├── MANIFEST.in
├── Makefile
├── OWNERS
├── README.md
├── bin/
│ ├── generate_tron_tab_completion_cache
│ ├── tronctl
│ ├── tronctl_tabcomplete.sh
│ ├── trond
│ ├── tronfig
│ ├── tronrepl
│ ├── tronview
│ └── tronview_tabcomplete.sh
├── contrib/
│ ├── migration_script.py
│ ├── mock_patch_checker.py
│ ├── namespace_cleanup.sh
│ ├── patch-config-loggers.diff
│ ├── sync-from-yelp-prod.sh
│ └── sync_namespaces_jobs.py
├── debian/
│ ├── changelog
│ ├── compat
│ ├── control
│ ├── copyright
│ ├── docs
│ ├── install
│ ├── pycompat
│ ├── pyversions
│ ├── rules
│ ├── tron.conffiles
│ ├── tron.default
│ ├── tron.dirs
│ ├── tron.example
│ ├── tron.links
│ ├── tron.manpages
│ ├── tron.postinst
│ ├── tron.service
│ ├── tron.upstart
│ └── watch
├── dev/
│ ├── config/
│ │ ├── MASTER.yaml
│ │ └── _manifest.yaml
│ └── logging.conf
├── docs/
│ └── source/
│ ├── _static/
│ │ └── nature.css
│ ├── command_context.rst
│ ├── conf.py
│ ├── config.rst
│ ├── developing.rst
│ ├── generated/
│ │ ├── modules.rst
│ │ ├── tron.actioncommand.rst
│ │ ├── tron.api.adapter.rst
│ │ ├── tron.api.async_resource.rst
│ │ ├── tron.api.auth.rst
│ │ ├── tron.api.controller.rst
│ │ ├── tron.api.requestargs.rst
│ │ ├── tron.api.resource.rst
│ │ ├── tron.api.rst
│ │ ├── tron.command_context.rst
│ │ ├── tron.commands.authentication.rst
│ │ ├── tron.commands.backfill.rst
│ │ ├── tron.commands.client.rst
│ │ ├── tron.commands.cmd_utils.rst
│ │ ├── tron.commands.display.rst
│ │ ├── tron.commands.retry.rst
│ │ ├── tron.commands.rst
│ │ ├── tron.config.config_parse.rst
│ │ ├── tron.config.config_utils.rst
│ │ ├── tron.config.manager.rst
│ │ ├── tron.config.rst
│ │ ├── tron.config.schedule_parse.rst
│ │ ├── tron.config.schema.rst
│ │ ├── tron.config.static_config.rst
│ │ ├── tron.core.action.rst
│ │ ├── tron.core.actiongraph.rst
│ │ ├── tron.core.actionrun.rst
│ │ ├── tron.core.job.rst
│ │ ├── tron.core.job_collection.rst
│ │ ├── tron.core.job_scheduler.rst
│ │ ├── tron.core.jobgraph.rst
│ │ ├── tron.core.jobrun.rst
│ │ ├── tron.core.recovery.rst
│ │ ├── tron.core.rst
│ │ ├── tron.eventbus.rst
│ │ ├── tron.kubernetes.rst
│ │ ├── tron.manhole.rst
│ │ ├── tron.mcp.rst
│ │ ├── tron.mesos.rst
│ │ ├── tron.metrics.rst
│ │ ├── tron.node.rst
│ │ ├── tron.prom_metrics.rst
│ │ ├── tron.rst
│ │ ├── tron.scheduler.rst
│ │ ├── tron.serialize.filehandler.rst
│ │ ├── tron.serialize.rst
│ │ ├── tron.serialize.runstate.dynamodb_state_store.rst
│ │ ├── tron.serialize.runstate.rst
│ │ ├── tron.serialize.runstate.shelvestore.rst
│ │ ├── tron.serialize.runstate.statemanager.rst
│ │ ├── tron.serialize.runstate.yamlstore.rst
│ │ ├── tron.ssh.rst
│ │ ├── tron.trondaemon.rst
│ │ ├── tron.utils.collections.rst
│ │ ├── tron.utils.crontab.rst
│ │ ├── tron.utils.exitcode.rst
│ │ ├── tron.utils.logreader.rst
│ │ ├── tron.utils.observer.rst
│ │ ├── tron.utils.persistable.rst
│ │ ├── tron.utils.proxy.rst
│ │ ├── tron.utils.queue.rst
│ │ ├── tron.utils.rst
│ │ ├── tron.utils.state.rst
│ │ ├── tron.utils.timeutils.rst
│ │ ├── tron.utils.trontimespec.rst
│ │ ├── tron.utils.twistedutils.rst
│ │ └── tron.yaml.rst
│ ├── index.rst
│ ├── jobs.rst
│ ├── man/
│ │ ├── tronctl.1
│ │ ├── trond.8
│ │ ├── tronfig.1
│ │ └── tronview.1
│ ├── man_tronctl.rst
│ ├── man_trond.rst
│ ├── man_tronfig.rst
│ ├── man_tronview.rst
│ ├── overview.rst
│ ├── sample_config.yaml
│ ├── tools.rst
│ ├── tron.yaml
│ ├── tronweb.rst
│ ├── tutorial.rst
│ └── whats-new.rst
├── itest.sh
├── mypy.ini
├── osx-bdb.sh
├── package.json
├── pyproject.toml
├── requirements-dev-minimal.txt
├── requirements-dev.txt
├── requirements-docs.txt
├── requirements-minimal.txt
├── requirements.txt
├── setup.cfg
├── setup.py
├── testfiles/
│ └── MASTER.yaml
├── testifycompat/
│ ├── __init__.py
│ ├── assertions.py
│ ├── bin/
│ │ ├── __init__.py
│ │ └── migrate.py
│ └── fixtures.py
├── tests/
│ ├── __init__.py
│ ├── actioncommand_test.py
│ ├── api/
│ │ ├── __init__.py
│ │ ├── adapter_test.py
│ │ ├── auth_test.py
│ │ ├── controller_test.py
│ │ ├── requestargs_test.py
│ │ └── resource_test.py
│ ├── assertions.py
│ ├── bin/
│ │ ├── __init__.py
│ │ ├── action_runner_test.py
│ │ ├── action_status_test.py
│ │ ├── check_tron_jobs_test.py
│ │ ├── get_tron_metrics_test.py
│ │ └── recover_batch_test.py
│ ├── command_context_test.py
│ ├── commands/
│ │ ├── __init__.py
│ │ ├── backfill_test.py
│ │ ├── client_test.py
│ │ ├── cmd_utils_test.py
│ │ ├── display_test.py
│ │ └── retry_test.py
│ ├── config/
│ │ ├── __init__.py
│ │ ├── config_parse_test.py
│ │ ├── config_utils_test.py
│ │ ├── manager_test.py
│ │ └── schedule_parse_test.py
│ ├── core/
│ │ ├── __init__.py
│ │ ├── action_test.py
│ │ ├── actiongraph_test.py
│ │ ├── actionrun_test.py
│ │ ├── job_collection_test.py
│ │ ├── job_scheduler_test.py
│ │ ├── job_test.py
│ │ ├── jobgraph_test.py
│ │ ├── jobrun_test.py
│ │ └── recovery_test.py
│ ├── data/
│ │ ├── logging.conf
│ │ └── test_config.yaml
│ ├── eventbus_test.py
│ ├── kubernetes_test.py
│ ├── mcp_reconfigure_test.py
│ ├── mcp_test.py
│ ├── mesos_test.py
│ ├── metrics_test.py
│ ├── mocks.py
│ ├── node_test.py
│ ├── sandbox.py
│ ├── scheduler_test.py
│ ├── serialize/
│ │ ├── __init__.py
│ │ ├── filehandler_test.py
│ │ └── runstate/
│ │ ├── __init__.py
│ │ ├── dynamodb_state_store_test.py
│ │ ├── shelvestore_test.py
│ │ ├── statemanager_test.py
│ │ └── yamlstore_test.py
│ ├── ssh_test.py
│ ├── test_id_rsa
│ ├── test_id_rsa.pub
│ ├── testingutils.py
│ ├── tools/
│ │ └── sync_tron_state_from_k8s_test.py
│ ├── trond_test.py
│ ├── trondaemon_test.py
│ └── utils/
│ ├── __init__.py
│ ├── collections_test.py
│ ├── crontab_test.py
│ ├── logreader_test.py
│ ├── observer_test.py
│ ├── proxy_test.py
│ ├── shortOutputTest.txt
│ ├── state_test.py
│ ├── timeutils_test.py
│ └── trontimespec_test.py
├── tools/
│ ├── action_dag_diagram.py
│ ├── compress_json.py
│ ├── inspect_serialized_state.py
│ ├── migration/
│ │ ├── migrate_config_0.2_to_0.3.py
│ │ ├── migrate_config_0.5.1_to_0.5.2.py
│ │ ├── migrate_state.py
│ │ └── migrate_state_1.3.15_to_1.4.0.py
│ ├── pickles_to_json.py
│ └── sync_tron_state_from_k8s.py
├── tox.ini
├── tron/
│ ├── __init__.py
│ ├── actioncommand.py
│ ├── api/
│ │ ├── __init__.py
│ │ ├── adapter.py
│ │ ├── async_resource.py
│ │ ├── auth.py
│ │ ├── controller.py
│ │ ├── requestargs.py
│ │ └── resource.py
│ ├── bin/
│ │ ├── action_runner.py
│ │ ├── action_status.py
│ │ ├── check_tron_datastore_staleness.py
│ │ ├── check_tron_jobs.py
│ │ ├── get_tron_metrics.py
│ │ └── recover_batch.py
│ ├── command_context.py
│ ├── commands/
│ │ ├── __init__.py
│ │ ├── authentication.py
│ │ ├── backfill.py
│ │ ├── client.py
│ │ ├── cmd_utils.py
│ │ ├── display.py
│ │ └── retry.py
│ ├── config/
│ │ ├── __init__.py
│ │ ├── config_parse.py
│ │ ├── config_utils.py
│ │ ├── manager.py
│ │ ├── schedule_parse.py
│ │ ├── schema.py
│ │ ├── static_config.py
│ │ └── tronfig_schema.json
│ ├── core/
│ │ ├── __init__.py
│ │ ├── action.py
│ │ ├── actiongraph.py
│ │ ├── actionrun.py
│ │ ├── job.py
│ │ ├── job_collection.py
│ │ ├── job_scheduler.py
│ │ ├── jobgraph.py
│ │ ├── jobrun.py
│ │ └── recovery.py
│ ├── default_config.yaml
│ ├── eventbus.py
│ ├── kubernetes.py
│ ├── logging.conf
│ ├── manhole.py
│ ├── mcp.py
│ ├── mesos.py
│ ├── metrics.py
│ ├── node.py
│ ├── prom_metrics.py
│ ├── scheduler.py
│ ├── serialize/
│ │ ├── __init__.py
│ │ ├── filehandler.py
│ │ └── runstate/
│ │ ├── __init__.py
│ │ ├── dynamodb_state_store.py
│ │ ├── shelvestore.py
│ │ ├── statemanager.py
│ │ └── yamlstore.py
│ ├── ssh.py
│ ├── trondaemon.py
│ ├── utils/
│ │ ├── __init__.py
│ │ ├── collections.py
│ │ ├── crontab.py
│ │ ├── exitcode.py
│ │ ├── logreader.py
│ │ ├── observer.py
│ │ ├── persistable.py
│ │ ├── proxy.py
│ │ ├── queue.py
│ │ ├── state.py
│ │ ├── timeutils.py
│ │ ├── trontimespec.py
│ │ └── twistedutils.py
│ └── yaml.py
├── tronweb/
│ ├── coffee/
│ │ ├── actionrun.coffee
│ │ ├── config.coffee
│ │ ├── dashboard.coffee
│ │ ├── graph.coffee
│ │ ├── job.coffee
│ │ ├── models.coffee
│ │ ├── navbar.coffee
│ │ ├── nodes.coffee
│ │ ├── routes.coffee
│ │ ├── timeline.coffee
│ │ └── views.coffee
│ ├── css/
│ │ ├── codemirror.css
│ │ ├── tronweb.less
│ │ └── whhg.css
│ ├── fonts/
│ │ └── SIL OFL Font License WebHostingHub Glyphs.txt
│ ├── index.html
│ └── js/
│ ├── backbone-min.js
│ ├── codemirror.js
│ ├── plugins.js
│ ├── underscore-min.js
│ ├── underscore.extra.js
│ ├── underscore.string.js
│ └── yaml.js
├── tronweb_tests/
│ ├── SpecRunner.html
│ ├── spec/
│ │ └── README
│ └── tests/
│ ├── actionrun_test.coffee
│ ├── dashboard_test.coffee
│ ├── navbar_test.coffee
│ ├── routes_test.coffee
│ └── timeline_test.coffee
└── yelp_package/
├── extra_requirements_yelp.txt
└── jammy/
└── Dockerfile
Showing preview only (264K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3312 symbols across 143 files)
FILE: contrib/migration_script.py
class bcolors (line 15) | class bcolors:
function parse_args (line 26) | def parse_args():
function check_job_if_running (line 57) | def check_job_if_running(jobs_status, job_name):
function command_jobs (line 75) | def command_jobs(command, jobs, args, ns=None):
function ssh_command (line 111) | def ssh_command(hostname, command):
function main (line 128) | def main():
FILE: contrib/mock_patch_checker.py
class MockChecker (line 6) | class MockChecker(ast.NodeVisitor):
method __init__ (line 7) | def __init__(self):
method init_module_imports (line 11) | def init_module_imports(self):
method check_files (line 15) | def check_files(self, files):
method check_file (line 19) | def check_file(self, filename):
method _call_uses_patch (line 34) | def _call_uses_patch(self, node):
method _call_uses_mock_patch (line 40) | def _call_uses_mock_patch(self, node):
method visit_Import (line 46) | def visit_Import(self, node):
method visit_ImportFrom (line 50) | def visit_ImportFrom(self, node):
method visit_Call (line 54) | def visit_Call(self, node):
function main (line 67) | def main(filenames):
FILE: contrib/sync_namespaces_jobs.py
function parse_args (line 15) | def parse_args():
function main (line 39) | def main():
FILE: docs/source/conf.py
class Mock (line 21) | class Mock(MagicMock):
method __getattr__ (line 23) | def __getattr__(cls, name):
FILE: testifycompat/__init__.py
function run (line 10) | def run():
FILE: testifycompat/assertions.py
function assert_equal (line 12) | def assert_equal(left, right, *args):
function assert_true (line 20) | def assert_true(val):
function assert_false (line 24) | def assert_false(val):
function assert_raises_and_contains (line 28) | def assert_raises_and_contains(exc, text, func, *args, **kwargs):
function assert_raises (line 37) | def assert_raises(exc, func=None, *args, **kwargs):
function assert_in (line 45) | def assert_in(item, container):
function assert_not_in (line 49) | def assert_not_in(item, container):
function assert_is (line 53) | def assert_is(left, right):
function assert_is_not (line 57) | def assert_is_not(left, right):
function assert_not_equal (line 61) | def assert_not_equal(left, right):
function assert_lt (line 65) | def assert_lt(left, right):
function assert_lte (line 69) | def assert_lte(left, right):
function assert_gt (line 73) | def assert_gt(left, right):
function assert_gte (line 77) | def assert_gte(left, right):
function assert_in_range (line 81) | def assert_in_range(val, start, end):
function assert_between (line 85) | def assert_between(val, start, end):
function assert_all_in (line 89) | def assert_all_in(left, right):
function assert_starts_with (line 98) | def assert_starts_with(val, prefix):
function assert_not_reached (line 102) | def assert_not_reached():
function assert_empty (line 106) | def assert_empty(iterable):
function assert_not_empty (line 110) | def assert_not_empty(iterable):
function assert_length (line 114) | def assert_length(sequence, expected):
function assert_sorted_equal (line 118) | def assert_sorted_equal(left, right):
function assert_isinstance (line 122) | def assert_isinstance(object_, type_):
FILE: testifycompat/bin/migrate.py
function replace (line 25) | def replace(pattern, repl):
function run_replacement (line 48) | def run_replacement(contents):
function strip_if_main_run (line 55) | def strip_if_main_run(contents):
function run_migration_on_file (line 63) | def run_migration_on_file(filename):
FILE: testifycompat/fixtures.py
function setup (line 13) | def setup(func):
function setup_teardown (line 17) | def setup_teardown(func):
function teardown (line 21) | def teardown(func):
function class_setup (line 29) | def class_setup(func):
function class_setup_teardown (line 33) | def class_setup_teardown(func):
function class_teardown (line 37) | def class_teardown(func):
function suite (line 45) | def suite(name, reason=None):
FILE: tests/actioncommand_test.py
class TestActionCommand (line 15) | class TestActionCommand(TestCase):
method setup_command (line 17) | def setup_command(self):
method test_init (line 22) | def test_init(self):
method test_init_no_serializer (line 25) | def test_init_no_serializer(self):
method test_started (line 32) | def test_started(self):
method test_started_already_started (line 37) | def test_started_already_started(self):
method test_exited (line 41) | def test_exited(self):
method test_exited_from_pending (line 47) | def test_exited_from_pending(self):
method test_exited_bad_state (line 51) | def test_exited_bad_state(self):
method test_write_stderr_no_fh (line 56) | def test_write_stderr_no_fh(self):
method test_write_stderr (line 61) | def test_write_stderr(self):
method test_done (line 72) | def test_done(self):
method test_done_bad_state (line 77) | def test_done_bad_state(self):
method test_handle_errback (line 80) | def test_handle_errback(self):
method test_is_unknown (line 86) | def test_is_unknown(self):
method test_is_failed (line 89) | def test_is_failed(self):
method test_is_failed_true (line 92) | def test_is_failed_true(self):
method test_is_complete (line 96) | def test_is_complete(self):
method test_is_complete_true (line 99) | def test_is_complete_true(self):
method test_is_done (line 103) | def test_is_done(self):
class TestCreateActionCommandFactoryFromConfig (line 110) | class TestCreateActionCommandFactoryFromConfig(TestCase):
method test_create_default_action_command_no_config (line 111) | def test_create_default_action_command_no_config(self):
method test_create_default_action_command (line 118) | def test_create_default_action_command(self):
method test_create_action_command_with_simple_runner (line 129) | def test_create_action_command_with_simple_runner(self):
class TestSubprocessActionRunnerFactory (line 143) | class TestSubprocessActionRunnerFactory(TestCase):
method setup_factory (line 145) | def setup_factory(self):
method test_from_config (line 153) | def test_from_config(self):
method test_create (line 161) | def test_create(self):
method test_build_command_complex_quoting (line 174) | def test_build_command_complex_quoting(self):
method test_build_stop_action_command (line 189) | def test_build_stop_action_command(self):
method test__eq__true (line 202) | def test__eq__true(self):
method test__eq__false (line 207) | def test__eq__false(self):
FILE: tests/api/adapter_test.py
class MockAdapter (line 24) | class MockAdapter(ReprAdapter):
method get_three (line 29) | def get_three(self):
method get_four (line 32) | def get_four(self):
class TestReprAdapter (line 36) | class TestReprAdapter(TestCase):
method setup_adapter (line 38) | def setup_adapter(self):
method test__init__ (line 42) | def test__init__(self):
method test_get_translation_mapping (line 46) | def test_get_translation_mapping(self):
method test_get_repr (line 53) | def test_get_repr(self):
class SampleClassStub (line 58) | class SampleClassStub:
method __init__ (line 59) | def __init__(self):
method expects_true (line 64) | def expects_true(self):
method expects_false (line 68) | def expects_false(self):
class TestToggleFlag (line 72) | class TestToggleFlag(TestCase):
method setup_stub (line 74) | def setup_stub(self):
method test_toggle_flag_true (line 77) | def test_toggle_flag_true(self):
method test_toggle_flag_false (line 80) | def test_toggle_flag_false(self):
class TestRunAdapter (line 84) | class TestRunAdapter(TestCase):
method setup_adapter (line 86) | def setup_adapter(self):
method test_get_state (line 90) | def test_get_state(self):
method test_get_node (line 94) | def test_get_node(self, mock_node_adapter):
method test_get_duration (line 101) | def test_get_duration(self):
class TestActionRunAdapter (line 106) | class TestActionRunAdapter(TestCase):
method setup_adapter (line 108) | def setup_adapter(self):
method teardown_adapter (line 115) | def teardown_adapter(self):
method test__init__ (line 118) | def test__init__(self):
method test_get_repr (line 123) | def test_get_repr(self):
class TestActionRunGraphAdapter (line 128) | class TestActionRunGraphAdapter(TestCase):
method setup_adapter (line 130) | def setup_adapter(self):
method test_get_repr (line 151) | def test_get_repr(self):
class TestJobRunAdapter (line 160) | class TestJobRunAdapter(TestCase):
method setup_adapter (line 162) | def setup_adapter(self):
method test__init__ (line 171) | def test__init__(self):
method test_get_runs (line 174) | def test_get_runs(self):
method test_get_runs_without_action_runs (line 178) | def test_get_runs_without_action_runs(self):
class TestNodeAdapter (line 183) | class TestNodeAdapter(TestCase):
method setup_adapter (line 185) | def setup_adapter(self):
method test_repr (line 189) | def test_repr(self):
class TestNodePoolAdapter (line 195) | class TestNodePoolAdapter(TestCase):
method setup_adapter (line 197) | def setup_adapter(self):
method test_repr (line 202) | def test_repr(self, mock_many):
class TestJobIndexAdapter (line 211) | class TestJobIndexAdapter(TestCase):
method setup_adapter (line 213) | def setup_adapter(self):
method test_repr (line 217) | def test_repr(self):
method test_get_actions (line 228) | def test_get_actions(self):
method test_get_actions_no_runs (line 239) | def test_get_actions_no_runs(self):
class TestSchedulerAdapter (line 245) | class TestSchedulerAdapter(TestCase):
method setup_adapter (line 247) | def setup_adapter(self):
method test_repr (line 252) | def test_repr(self, mock_get_jitter):
FILE: tests/api/auth_test.py
function mock_auth_filter (line 12) | def mock_auth_filter():
function mock_request (line 17) | def mock_request(path: str, token: str, method: str):
function test_is_request_authorized (line 23) | def test_is_request_authorized(mock_auth_filter):
function test_is_request_authorized_fail (line 45) | def test_is_request_authorized_fail(mock_auth_filter):
function test_is_request_authorized_malformed (line 52) | def test_is_request_authorized_malformed(mock_auth_filter):
function test_is_request_authorized_no_enforce (line 59) | def test_is_request_authorized_no_enforce(mock_auth_filter):
function test_is_request_authorized_disabled (line 69) | def test_is_request_authorized_disabled(mock_auth_filter):
function test_extract_service_from_path (line 88) | def test_extract_service_from_path(path, expected):
FILE: tests/api/controller_test.py
class TestJobCollectionController (line 20) | class TestJobCollectionController:
method setup_controller (line 22) | def setup_controller(self):
method test_handle_command_unknown (line 30) | def test_handle_command_unknown(self):
method test_handle_command_move_non_existing_job (line 35) | def test_handle_command_move_non_existing_job(self):
method test_handle_command_move_to_existing_job (line 44) | def test_handle_command_move_to_existing_job(self):
method test_handle_command_move (line 53) | def test_handle_command_move(self):
class TestActionRunController (line 63) | class TestActionRunController:
method setup_controller (line 65) | def setup_controller(self):
method test_handle_command_start_failed (line 78) | def test_handle_command_start_failed(self):
method test_handle_command_recover_failed (line 84) | def test_handle_command_recover_failed(self):
method test_handle_command_mapped_command (line 90) | def test_handle_command_mapped_command(self):
method test_handle_command_mapped_command_failed (line 95) | def test_handle_command_mapped_command_failed(self):
method test_handle_termination_not_implemented (line 100) | def test_handle_termination_not_implemented(self):
method test_handle_termination_success_without_extra_msg (line 105) | def test_handle_termination_success_without_extra_msg(self):
method test_handle_termination_success_with_extra_msg (line 110) | def test_handle_termination_success_with_extra_msg(self):
method test_handle_retry_default (line 116) | def test_handle_retry_default(self):
method test_handle_retry_new_command (line 120) | def test_handle_retry_new_command(self):
class TestJobRunController (line 125) | class TestJobRunController:
method setup_controller (line 127) | def setup_controller(self):
method test_handle_command_restart (line 139) | def test_handle_command_restart(self):
method test_handle_mapped_command (line 145) | def test_handle_mapped_command(self):
method test_handle_mapped_command_failure (line 150) | def test_handle_mapped_command_failure(self):
class TestJobController (line 157) | class TestJobController:
method setup_controller (line 159) | def setup_controller(self):
method test_handle_command_enable (line 163) | def test_handle_command_enable(self):
method test_handle_command_disable (line 167) | def test_handle_command_disable(self):
method test_handle_command_start (line 171) | def test_handle_command_start(self):
class TestConfigController (line 177) | class TestConfigController:
method setup_controller (line 179) | def setup_controller(self):
method test_get_config_content_new (line 185) | def test_get_config_content_new(self):
method test_get_config_content_old (line 191) | def test_get_config_content_old(self):
method test_read_config (line 198) | def test_read_config(self):
method test_update_config (line 207) | def test_update_config(self):
method test_update_config_failure (line 215) | def test_update_config_failure(self):
method test_update_config_hash_mismatch (line 238) | def test_update_config_hash_mismatch(self):
method test_delete_config (line 243) | def test_delete_config(self):
method test_delete_config_failure (line 251) | def test_delete_config_failure(self):
method test_delete_config_hash_mismatch (line 260) | def test_delete_config_hash_mismatch(self):
method test_delete_config_content_not_empty (line 265) | def test_delete_config_content_not_empty(self):
method test_get_namespaces (line 270) | def test_get_namespaces(self):
class TestEventsController (line 276) | class TestEventsController:
method setup (line 278) | def setup(self):
method test_info (line 285) | def test_info(self):
method test_publish (line 292) | def test_publish(self):
method test_discard (line 313) | def test_discard(self):
FILE: tests/api/requestargs_test.py
class TestRequestArgs (line 14) | class TestRequestArgs(TestCase):
method setup_args (line 16) | def setup_args(self):
method _add_arg (line 26) | def _add_arg(self, name, value):
method test_get_integer_valid_int (line 33) | def test_get_integer_valid_int(self):
method test_get_integer_invalid_int (line 37) | def test_get_integer_invalid_int(self):
method test_get_integer_missing (line 41) | def test_get_integer_missing(self):
method test_get_string (line 44) | def test_get_string(self):
method test_get_string_missing (line 48) | def test_get_string_missing(self):
method test_get_bool (line 51) | def test_get_bool(self):
method test_get_bool_false (line 54) | def test_get_bool_false(self):
method test_get_bool_missing (line 58) | def test_get_bool_missing(self):
method test_get_datetime_valid (line 61) | def test_get_datetime_valid(self):
method test_get_datetime_invalid (line 64) | def test_get_datetime_invalid(self):
method test_get_datetime_missing (line 68) | def test_get_datetime_missing(self):
FILE: tests/api/resource_test.py
function build_request (line 41) | def build_request(**kwargs):
function mock_request (line 47) | def mock_request():
function mock_respond (line 52) | def mock_respond():
class WWWTestCase (line 62) | class WWWTestCase:
function test_respond (line 78) | def test_respond(response, code, expected_code):
class TestHandleCommand (line 84) | class TestHandleCommand:
method mock_respond (line 86) | def mock_respond(self, mock_respond):
method test_handle_command_unknown (line 91) | def test_handle_command_unknown(self, mock_respond):
method test_handle_command (line 105) | def test_handle_command(self, mock_respond):
method test_handle_command_error (line 116) | def test_handle_command_error(self, mock_respond):
class TestActionRunResource (line 127) | class TestActionRunResource(WWWTestCase):
method setup_resource (line 129) | def setup_resource(self):
method test_render_GET (line 138) | def test_render_GET(self, mock_respond):
class TestJobrunResource (line 147) | class TestJobrunResource(WWWTestCase):
method setup_resource (line 149) | def setup_resource(self):
method test_render_GET (line 154) | def test_render_GET(self, mock_request):
class TestApiRootResource (line 159) | class TestApiRootResource(WWWTestCase):
method setup_resource (line 161) | def setup_resource(self):
method test__init__ (line 165) | def test__init__(self):
method test_render_GET (line 177) | def test_render_GET(self):
class TestRootResource (line 187) | class TestRootResource(WWWTestCase):
method setup_resource (line 189) | def setup_resource(self):
method test_render_GET (line 194) | def test_render_GET(self):
method test_get_children (line 201) | def test_get_children(self):
class TestActionRunHistoryResource (line 205) | class TestActionRunHistoryResource(WWWTestCase):
method setup_resource (line 207) | def setup_resource(self):
method test_render_GET (line 211) | def test_render_GET(self, request):
class TestJobCollectionResource (line 216) | class TestJobCollectionResource(WWWTestCase):
method setup_resource (line 218) | def setup_resource(self):
method test_render_GET (line 223) | def test_render_GET(self):
method test_getChild (line 229) | def test_getChild(self):
method test_getChild_missing_job (line 233) | def test_getChild_missing_job(self):
class TestJobResource (line 238) | class TestJobResource(WWWTestCase):
method setup_resource (line 240) | def setup_resource(self):
method test_render_GET (line 260) | def test_render_GET(self, mock_request):
method test_get_run_from_identifier_HEAD (line 264) | def test_get_run_from_identifier_HEAD(self):
method test_get_run_from_identifier_number (line 269) | def test_get_run_from_identifier_number(self):
method test_get_run_from_identifier_negative_index (line 275) | def test_get_run_from_identifier_negative_index(self):
method test_getChild (line 280) | def test_getChild(self):
method test_getChild_action_run_history (line 286) | def test_getChild_action_run_history(self):
class TestConfigResource (line 300) | class TestConfigResource:
method setup_resource (line 302) | def setup_resource(self):
method test_render_GET (line 309) | def test_render_GET(self, mock_respond):
method test_render_POST_update (line 319) | def test_render_POST_update(self, mock_respond):
method test_render_POST_delete (line 330) | def test_render_POST_delete(self, mock_respond):
class TestStatusResource (line 342) | class TestStatusResource:
method test_render_GET (line 343) | def test_render_GET(self, request, mock_respond):
class TestMetricsResource (line 359) | class TestMetricsResource:
method test_render_GET (line 361) | def test_render_GET(self, mock_view_metrics, request, mock_respond):
class TestTronSite (line 370) | class TestTronSite:
method test_log_request (line 372) | def test_log_request(self, mock_meter):
FILE: tests/assertions.py
function assert_raises (line 8) | def assert_raises(expected_exception_class, callable_obj, *args, **kwargs):
function assert_length (line 20) | def assert_length(sequence, expected, msg=None):
function assert_call (line 27) | def assert_call(mock, call_idx, *args, **kwargs):
function assert_mock_calls (line 34) | def assert_mock_calls(expected, mock_calls):
FILE: tests/bin/action_runner_test.py
class TestStatusFile (line 13) | class TestStatusFile(TestCase):
method setup_status_file (line 15) | def setup_status_file(self):
method test_get_content (line 19) | def test_get_content(self):
class TestRegister (line 43) | class TestRegister(TestCase):
method patch_sys (line 48) | def patch_sys(self):
method test_validate_output_dir_does_not_exist (line 62) | def test_validate_output_dir_does_not_exist(self):
method test_validate_output_dir_does_not_exist_create_fails (line 68) | def test_validate_output_dir_does_not_exist_create_fails(self):
method test_validate_output_dir_exists_not_writable (line 75) | def test_validate_output_dir_exists_not_writable(self):
method test_run_proc (line 81) | def test_run_proc(self):
class TestBuildEnvironment (line 101) | class TestBuildEnvironment:
method test_build_environment (line 102) | def test_build_environment(self):
method test_build_environment_invalid_run_id (line 118) | def test_build_environment_invalid_run_id(self):
method test_build_environment_too_long_run_id (line 134) | def test_build_environment_too_long_run_id(self):
class TestBuildLabels (line 151) | class TestBuildLabels:
method test_build_labels (line 152) | def test_build_labels(self):
method test_build_labels_with_merging (line 159) | def test_build_labels_with_merging(self):
method test_build_labels_with_merging_on_unknown (line 168) | def test_build_labels_with_merging_on_unknown(self):
method test_build_labels_invalid_run_id (line 177) | def test_build_labels_invalid_run_id(self):
method test_build_labels_too_long_run_id (line 184) | def test_build_labels_too_long_run_id(self):
method test_build_labels_with_attempt_number_zero (line 191) | def test_build_labels_with_attempt_number_zero(self):
method test_build_labels_with_attempt_number_retry (line 199) | def test_build_labels_with_attempt_number_retry(self):
method test_build_labels_with_attempt_number_and_original_labels (line 207) | def test_build_labels_with_attempt_number_and_original_labels(self):
method test_build_labels_without_attempt_number_omits_label (line 217) | def test_build_labels_without_attempt_number_omits_label(self):
FILE: tests/bin/action_status_test.py
class TestActionStatus (line 11) | class TestActionStatus(TestCase):
method setup_status_file (line 13) | def setup_status_file(self):
method test_send_signal (line 32) | def test_send_signal(self, mock_getpgid, mock_kill):
method test_get_field_retrieves_last_entry (line 37) | def test_get_field_retrieves_last_entry(self):
method test_get_field_none (line 52) | def test_get_field_none(self):
FILE: tests/bin/check_tron_jobs_test.py
function mock_run_interval (line 15) | def mock_run_interval():
class TestCheckJobs (line 20) | class TestCheckJobs(TestCase):
method test_check_job_result_exception (line 25) | def test_check_job_result_exception(
method test_job_succeeded (line 54) | def test_job_succeeded(self):
method test_job_running_and_action_succeeded (line 95) | def test_job_running_and_action_succeeded(self):
method test_get_relevant_action_picks_the_first_one_succeeded (line 146) | def test_get_relevant_action_picks_the_first_one_succeeded(self):
method test_job_failed (line 191) | def test_job_failed(self):
method test_most_recent_end_time_job_failed (line 232) | def test_most_recent_end_time_job_failed(self):
method test_rerun_job_failed (line 276) | def test_rerun_job_failed(self):
method test_job_running_but_action_failed_already (line 332) | def test_job_running_but_action_failed_already(self):
method test_get_relevant_action_picks_the_one_that_failed (line 383) | def test_get_relevant_action_picks_the_one_that_failed(self):
method test_job_next_run_starting_no_overlap_is_stuck (line 438) | def test_job_next_run_starting_no_overlap_is_stuck(self):
method test_job_next_run_starting_overlap_allowed_not_stuck (line 467) | def test_job_next_run_starting_overlap_allowed_not_stuck(self):
method test_job_next_run_running_no_queueing_not_stuck (line 509) | def test_job_next_run_running_no_queueing_not_stuck(self):
method test_job_next_run_starting_no_queueing_not_stuck (line 552) | def test_job_next_run_starting_no_queueing_not_stuck(self):
method test_job_running_job_exceeds_expected_runtime (line 595) | def test_job_running_job_exceeds_expected_runtime(self):
method test_job_starting_job_exceeds_expected_runtime (line 633) | def test_job_starting_job_exceeds_expected_runtime(self):
method test_job_waiting_job_exceeds_expected_runtime_already_started (line 671) | def test_job_waiting_job_exceeds_expected_runtime_already_started(self):
method test_job_running_action_exceeds_expected_runtime (line 709) | def test_job_running_action_exceeds_expected_runtime(self):
method test_job_running_action_exceeds_expected_runtime_and_other_action_failed (line 779) | def test_job_running_action_exceeds_expected_runtime_and_other_action_...
method test_job_stuck_when_runtime_not_sorted (line 826) | def test_job_stuck_when_runtime_not_sorted(self):
method test_get_relevant_action_pick_the_one_stuck (line 855) | def test_get_relevant_action_pick_the_one_stuck(self):
method test_get_relevant_action_pick_the_one_exceeds_expected_runtime (line 896) | def test_get_relevant_action_pick_the_one_exceeds_expected_runtime(self):
method test_get_relevant_action_pick_the_one_starting (line 938) | def test_get_relevant_action_pick_the_one_starting(self):
method test_get_relevant_action_pick_the_one_exceeds_expected_runtime_with_long_duration (line 980) | def test_get_relevant_action_pick_the_one_exceeds_expected_runtime_wit...
method test_no_job_scheduled_or_queuing (line 1027) | def test_no_job_scheduled_or_queuing(self):
method test_job_no_runs_to_check (line 1067) | def test_job_no_runs_to_check(self):
method test_job_has_no_runs_at_all (line 1087) | def test_job_has_no_runs_at_all(self):
method test_job_unknown (line 1098) | def test_job_unknown(self):
method test_job_running_but_action_unknown_already (line 1139) | def test_job_running_but_action_unknown_already(self):
method test_job_waiting_but_action_unknown_already (line 1190) | def test_job_waiting_but_action_unknown_already(self):
method test_guess_realert_every (line 1242) | def test_guess_realert_every(self):
method test_guess_realert_every_no_action_run_starts (line 1280) | def test_guess_realert_every_no_action_run_starts(self):
method test_guess_realert_every_queue_job (line 1319) | def test_guess_realert_every_queue_job(self):
method test_guess_realert_every_frequent_run (line 1350) | def test_guess_realert_every_frequent_run(self):
method test_guess_realert_every_first_time_job (line 1384) | def test_guess_realert_every_first_time_job(self):
class TestCheckPreciousJobs (line 1403) | class TestCheckPreciousJobs:
method setup_job (line 1405) | def setup_job(self):
method test_sort_runs_by_interval_day (line 1482) | def test_sort_runs_by_interval_day(self):
method test_sort_runs_by_interval_day_empty_buckets (line 1497) | def test_sort_runs_by_interval_day_empty_buckets(self):
method test_sort_runs_by_interval_day_old_empty_buckets (line 1517) | def test_sort_runs_by_interval_day_old_empty_buckets(self):
method test_compute_check_result_for_job_not_precious (line 1550) | def test_compute_check_result_for_job_not_precious(
method test_compute_check_result_for_job_disabled (line 1588) | def test_compute_check_result_for_job_disabled(self, mock_client):
method test_compute_check_result_for_job_enabled (line 1612) | def test_compute_check_result_for_job_enabled(
FILE: tests/bin/get_tron_metrics_test.py
function test_send_data_metric (line 9) | def test_send_data_metric():
function test_send_data_metric_dry_run (line 35) | def test_send_data_metric_dry_run():
function test_send_counter (line 49) | def test_send_counter(mock_send_data_metric):
function test_send_gauge (line 65) | def test_send_gauge(mock_send_data_metric):
function test_send_meter (line 81) | def test_send_meter(mock_send_counter):
function test_send_histogram (line 89) | def test_send_histogram(mock_send_gauge):
function test_send_timer (line 112) | def test_send_timer(mock_send_meter, mock_send_histogram):
function test_send_metrics (line 122) | def test_send_metrics(cluster):
FILE: tests/bin/recover_batch_test.py
function mock_file (line 12) | def mock_file():
function test_notify (line 27) | def test_notify(mock_get_exit_code, mock_reactor, exit_code, error_msg, ...
function test_get_exit_code (line 77) | def test_get_exit_code(
function test_read_last_yaml_roundtrip (line 94) | def test_read_last_yaml_roundtrip(mock_file):
function test_run (line 118) | def test_run(
FILE: tests/command_context_test.py
class TestEmptyContext (line 18) | class TestEmptyContext(TestCase):
method build_context (line 20) | def build_context(self):
method test__getitem__ (line 23) | def test__getitem__(self):
method test_get (line 26) | def test_get(self):
class TestBuildFilledContext (line 30) | class TestBuildFilledContext(TestCase):
method test_build_filled_context_no_objects (line 31) | def test_build_filled_context_no_objects(self):
method test_build_filled_context_single (line 36) | def test_build_filled_context_single(self):
method test_build_filled_context_chain (line 43) | def test_build_filled_context_chain(self):
class SimpleContextTestCaseBase (line 51) | class SimpleContextTestCaseBase(TestCase):
method test_hit (line 54) | def test_hit(self):
method test_miss (line 57) | def test_miss(self):
method test_get_hit (line 60) | def test_get_hit(self):
method test_get_miss (line 63) | def test_get_miss(self):
class SimpleDictContextTestCase (line 67) | class SimpleDictContextTestCase(SimpleContextTestCaseBase):
method build_context (line 69) | def build_context(self):
class SimpleObjectContextTestCase (line 73) | class SimpleObjectContextTestCase(SimpleContextTestCaseBase):
method build_context (line 75) | def build_context(self):
class ChainedDictContextTestCase (line 82) | class ChainedDictContextTestCase(SimpleContextTestCaseBase):
method build_context (line 84) | def build_context(self):
method test_chain_get (line 93) | def test_chain_get(self):
class ChainedDictOverrideContextTestCase (line 97) | class ChainedDictOverrideContextTestCase(SimpleContextTestCaseBase):
method build_context (line 99) | def build_context(self):
method test_chain_get (line 108) | def test_chain_get(self):
class ChainedObjectOverrideContextTestCase (line 112) | class ChainedObjectOverrideContextTestCase(SimpleContextTestCaseBase):
method build_context (line 114) | def build_context(self):
method test_chain_get (line 126) | def test_chain_get(self):
class TestJobContext (line 130) | class TestJobContext(TestCase):
method setup_job (line 132) | def setup_job(self):
method test_name (line 146) | def test_name(self):
method test__getitem__last_success (line 149) | def test__getitem__last_success(self):
method test__getitem__last_success_bad_date_spec (line 157) | def test__getitem__last_success_bad_date_spec(self):
method test__getitem__last_success_bad_date_name (line 161) | def test__getitem__last_success_bad_date_name(self):
method test__getitem__last_success_no_date_spec (line 165) | def test__getitem__last_success_no_date_spec(self):
method test__getitem__missing (line 169) | def test__getitem__missing(self):
method test_namespace (line 172) | def test_namespace(self):
class TestJobRunContext (line 176) | class TestJobRunContext(TestCase):
method setup_context (line 178) | def setup_context(self):
method test_cleanup_job_status (line 182) | def test_cleanup_job_status(self):
method test_cleanup_job_status_failure (line 187) | def test_cleanup_job_status_failure(self):
method test_runid (line 191) | def test_runid(self):
method test_manual_run (line 194) | def test_manual_run(self):
method test__getitem__ (line 198) | def test__getitem__(self, mock_date_math):
class TestActionRunContext (line 205) | class TestActionRunContext(TestCase):
method build_context (line 207) | def build_context(self):
method test_actionname (line 216) | def test_actionname(self):
method test_node_hostname (line 219) | def test_node_hostname(self):
class TestFiller (line 223) | class TestFiller(TestCase):
method setup_filler (line 225) | def setup_filler(self):
method test_filler_with_job__getitem__ (line 228) | def test_filler_with_job__getitem__(self):
method test_filler_with_job_run__getitem__ (line 233) | def test_filler_with_job_run__getitem__(self):
FILE: tests/commands/backfill_test.py
function mock_sleep (line 15) | def mock_sleep():
function mock_client (line 24) | def mock_client():
function mock_urlopen (line 30) | def mock_urlopen(): # prevent any requests from being made
function mock_client_request (line 36) | def mock_client_request():
function fake_backfill_run (line 43) | def fake_backfill_run(mock_client):
function test_backfill_run_create (line 61) | def test_backfill_run_create(mock_client_request, fake_backfill_run, eve...
function test_backfill_run_get_run_id (line 75) | def test_backfill_run_get_run_id(mock_get_obj_type, fake_backfill_run, e...
function test_backfill_run_sync_state (line 89) | def test_backfill_run_sync_state(fake_backfill_run, event_loop, job_run_...
function test_backfill_run_watch_until_completion (line 95) | def test_backfill_run_watch_until_completion(fake_backfill_run, event_lo...
function test_backfill_run_cancel (line 111) | def test_backfill_run_cancel(
function test_run_backfill_for_date_range_job_dne (line 126) | def test_run_backfill_for_date_range_job_dne(mock_get_obj_type, event_lo...
function test_run_backfill_for_date_range_not_a_job (line 136) | def test_run_backfill_for_date_range_not_a_job(mock_get_obj_type, event_...
function test_run_backfill_for_date_range_normal (line 153) | def test_run_backfill_for_date_range_normal(mock_get_obj_type, event_loo...
FILE: tests/commands/client_test.py
function build_file_mock (line 19) | def build_file_mock(content):
class TestRequest (line 26) | class TestRequest(TestCase):
method setup_options (line 28) | def setup_options(self):
method patch_urllib (line 32) | def patch_urllib(self):
method test_build_url_request_no_data (line 40) | def test_build_url_request_no_data(self):
method test_build_url_request_with_data (line 46) | def test_build_url_request_with_data(self):
method test_load_response_content_success (line 56) | def test_load_response_content_success(self, _):
method test_request_http_error (line 64) | def test_request_http_error(self, _):
method test_request_url_error (line 77) | def test_request_url_error(self, _):
method test_request_success (line 83) | def test_request_success(self):
class TestClientRequest (line 90) | class TestClientRequest(TestCase):
method setup_client (line 92) | def setup_client(self):
method patch_request (line 97) | def patch_request(self):
method test_request_error (line 104) | def test_request_error(self):
method test_request_success (line 119) | def test_request_success(self):
class TestClient (line 126) | class TestClient(TestCase):
method setup_client (line 128) | def setup_client(self):
method test_config_post (line 133) | def test_config_post(self):
method test_config_get_default (line 144) | def test_config_get_default(self):
method test_http_get (line 150) | def test_http_get(self):
method test_action_runs (line 154) | def test_action_runs(self):
method test_job_runs (line 160) | def test_job_runs(self):
method test_job (line 166) | def test_job(self):
method test_jobs (line 172) | def test_jobs(self):
class TestUserAttribution (line 179) | class TestUserAttribution(TestCase):
method test_default_user_agent (line 180) | def test_default_user_agent(self):
method test_attributed_user_agent (line 191) | def test_attributed_user_agent(self):
class TestGetUrl (line 203) | class TestGetUrl(TestCase):
method test_get_job_url_for_action_run (line 204) | def test_get_job_url_for_action_run(self):
method test_get_job_url_for_job (line 208) | def test_get_job_url_for_job(self):
class TestGetContentFromIdentifier (line 213) | class TestGetContentFromIdentifier(TestCase):
method setup_client (line 215) | def setup_client(self):
method test_get_url_from_identifier_job_no_namespace (line 226) | def test_get_url_from_identifier_job_no_namespace(self):
method test_get_url_from_identifier_job (line 231) | def test_get_url_from_identifier_job(self):
method test_get_url_from_identifier_job_run (line 239) | def test_get_url_from_identifier_job_run(self):
method test_get_url_from_identifier_action_run (line 247) | def test_get_url_from_identifier_action_run(self):
method test_get_url_from_identifier_job_no_namespace_not_master (line 255) | def test_get_url_from_identifier_job_no_namespace_not_master(self):
method test_get_url_from_identifier_no_match (line 260) | def test_get_url_from_identifier_no_match(self):
FILE: tests/commands/cmd_utils_test.py
class TestGetConfig (line 11) | class TestGetConfig(TestCase):
method patch_environment (line 13) | def patch_environment(self):
method test_read_config_missing (line 19) | def test_read_config_missing(self):
method test_read_config (line 23) | def test_read_config(self):
method test_get_client_config (line 27) | def test_get_client_config(self, mock_access):
method test_filter_jobs_actions_runs_with_nothing (line 33) | def test_filter_jobs_actions_runs_with_nothing(self):
method test_filter_jobs_actions_runs_with_almost_a_job (line 52) | def test_filter_jobs_actions_runs_with_almost_a_job(self):
method test_filter_jobs_actions_runs_with_a_job_run (line 70) | def test_filter_jobs_actions_runs_with_a_job_run(self):
method test_filter_jobs_actions_runs_with_a_job_run_and_id (line 89) | def test_filter_jobs_actions_runs_with_a_job_run_and_id(self):
class TestBuildOptionParser (line 108) | class TestBuildOptionParser(TestCase):
method test_build_option_parser (line 109) | def test_build_option_parser(self):
class TestSuggestions (line 141) | class TestSuggestions(TestCase):
method test_suggest_possibilities_none (line 142) | def test_suggest_possibilities_none(self):
method test_suggest_possibilities_many (line 147) | def test_suggest_possibilities_many(self):
method test_suggest_possibilities_one (line 155) | def test_suggest_possibilities_one(self):
FILE: tests/commands/display_test.py
class TestDisplayJobRuns (line 14) | class TestDisplayJobRuns(TestCase):
method setup_data (line 16) | def setup_data(self):
method test_format (line 42) | def test_format(self):
class TestDisplayJobs (line 48) | class TestDisplayJobs(TestCase):
method setup_data (line 50) | def setup_data(self):
method do_format (line 66) | def do_format(self):
method test_format (line 71) | def test_format(self):
class TestDisplayActions (line 76) | class TestDisplayActions(TestCase):
method setup_data (line 78) | def setup_data(self):
method format_lines (line 150) | def format_lines(self):
method test_format (line 154) | def test_format(self):
class TestAddColorForState (line 159) | class TestAddColorForState(TestCase):
method enable_color (line 161) | def enable_color(self):
method test_add_red (line 165) | def test_add_red(self):
method test_add_green (line 169) | def test_add_green(self):
method test_add_blue (line 173) | def test_add_blue(self):
class TestDisplayNode (line 178) | class TestDisplayNode(TestCase):
method test_display_node (line 186) | def test_display_node(self):
method test_display_node_pool (line 190) | def test_display_node_pool(self):
FILE: tests/commands/retry_test.py
function _empty_coro (line 10) | async def _empty_coro(*args, **kwargs):
function mock_sleep (line 15) | def mock_sleep():
function mock_client (line 21) | def mock_client():
function mock_urlopen (line 28) | def mock_urlopen(): # prevent any requests from being made
function mock_client_request (line 34) | def mock_client_request():
function test_retry_action_init_not_an_action (line 46) | def test_retry_action_init_not_an_action(mock_get_obj_type, mock_client):
function fake_retry_action (line 53) | def fake_retry_action(mock_client):
function test_retry_action_init_ok (line 85) | def test_retry_action_init_ok(fake_retry_action):
function test_check_trigger_statuses (line 100) | def test_check_trigger_statuses(fake_retry_action, event_loop):
function test_check_required_actions_statuses (line 109) | def test_check_required_actions_statuses(fake_retry_action, event_loop):
function test_can_retry (line 123) | def test_can_retry(fake_retry_action, event_loop, expected, triggered_by...
function test_wait_for_deps_timeout (line 129) | def test_wait_for_deps_timeout(fake_retry_action, event_loop):
function test_wait_for_deps_all_deps_done (line 135) | def test_wait_for_deps_all_deps_done(fake_retry_action, event_loop):
function test_issue_retry (line 159) | def test_issue_retry(fake_retry_action, mock_client_request, event_loop,...
function test_wait_for_retry_deps_not_done (line 165) | def test_wait_for_retry_deps_not_done(fake_retry_action, mock_client_req...
function test_wait_for_retry_deps_done (line 173) | def test_wait_for_retry_deps_done(fake_retry_action, mock_client_request...
function test_retry_actions (line 193) | def test_retry_actions(mock_retry_action, mock_client, event_loop):
FILE: tests/config/config_parse_test.py
function make_ssh_options (line 47) | def make_ssh_options():
function make_mock_schedule (line 60) | def make_mock_schedule():
function make_command_context (line 71) | def make_command_context():
function make_nodes (line 78) | def make_nodes():
function make_node_pools (line 95) | def make_node_pools():
function make_mesos_options (line 104) | def make_mesos_options():
function make_k8s_options (line 118) | def make_k8s_options():
function make_action (line 122) | def make_action(**kwargs):
function make_cleanup_action (line 131) | def make_cleanup_action(**kwargs):
function make_job (line 139) | def make_job(**kwargs):
function make_master_jobs (line 169) | def make_master_jobs():
function make_tron_config (line 328) | def make_tron_config(
function make_named_tron_config (line 358) | def make_named_tron_config(jobs=None):
class ConfigTestCase (line 362) | class ConfigTestCase(TestCase):
method test_attributes (line 490) | def test_attributes(self):
method test_empty_node_test (line 511) | def test_empty_node_test(self):
class TestNamedConfig (line 515) | class TestNamedConfig(TestCase):
method test_attributes (line 518) | def test_attributes(self):
method test_attributes_with_master_context (line 546) | def test_attributes_with_master_context(self):
method test_invalid_job_node_with_master_context (line 589) | def test_invalid_job_node_with_master_context(self):
method test_invalid_action_node_with_master_context (line 620) | def test_invalid_action_node_with_master_context(self):
class TestJobConfig (line 659) | class TestJobConfig(TestCase):
method test_no_actions (line 660) | def test_no_actions(self):
method test_empty_actions (line 676) | def test_empty_actions(self):
method test_dupe_names (line 697) | def test_dupe_names(self):
method test_bad_requires (line 721) | def test_bad_requires(self):
method test_circular_dependency (line 754) | def test_circular_dependency(self):
method test_circular_dependency_multiaction (line 786) | def test_circular_dependency_multiaction(self):
method test_config_cleanup_name_collision (line 833) | def test_config_cleanup_name_collision(self):
method test_config_cleanup_action_name (line 855) | def test_config_cleanup_action_name(self):
method test_config_cleanup_requires (line 879) | def test_config_cleanup_requires(self):
method test_validate_job_no_actions (line 903) | def test_validate_job_no_actions(self):
class TestValidSecretSource (line 926) | class TestValidSecretSource(TestCase):
method test_missing_secret_name (line 927) | def test_missing_secret_name(self):
method test_validate_job_extra_secret_env (line 935) | def test_validate_job_extra_secret_env(self):
method test_valid_job_secret_env_success (line 946) | def test_valid_job_secret_env_success(self):
class TestNodeConfig (line 958) | class TestNodeConfig(TestCase):
method test_validate_node_pool (line 959) | def test_validate_node_pool(self):
method test_overlap_node_and_node_pools (line 966) | def test_overlap_node_and_node_pools(self):
method test_invalid_node_name (line 979) | def test_invalid_node_name(self):
method test_invalid_nested_node_pools (line 1000) | def test_invalid_nested_node_pools(self):
method test_invalid_node_pool_config (line 1028) | def test_invalid_node_pool_config(self):
method test_invalid_named_update (line 1056) | def test_invalid_named_update(self):
class TestValidateJobs (line 1068) | class TestValidateJobs(TestCase):
method test_valid_jobs_success (line 1069) | def test_valid_jobs_success(self):
class TestValidCleanupActionName (line 1187) | class TestValidCleanupActionName(TestCase):
method test_valid_cleanup_action_name_pass (line 1188) | def test_valid_cleanup_action_name_pass(self):
method test_valid_cleanup_action_name_fail (line 1192) | def test_valid_cleanup_action_name_fail(self):
class TestValidOutputStreamDir (line 1201) | class TestValidOutputStreamDir(TestCase):
method setup_dir (line 1203) | def setup_dir(self):
method teardown_dir (line 1207) | def teardown_dir(self):
method test_valid_dir (line 1210) | def test_valid_dir(self):
method test_missing_dir (line 1214) | def test_missing_dir(self):
method test_missing_with_partial_context (line 1232) | def test_missing_with_partial_context(self):
class TestBuildFormatStringValidator (line 1239) | class TestBuildFormatStringValidator(TestCase):
method setup_keys (line 1241) | def setup_keys(self):
method test_validator_passes (line 1245) | def test_validator_passes(self):
method test_validator_unknown_variable_error (line 1249) | def test_validator_unknown_variable_error(self):
method test_validator_passes_with_context (line 1259) | def test_validator_passes_with_context(self):
method test_validator_valid_string_without_no_percent_escape (line 1269) | def test_validator_valid_string_without_no_percent_escape(self):
class TestValidateConfigMapping (line 1280) | class TestValidateConfigMapping(TestCase):
method test_validate_config_mapping_missing_master (line 1283) | def test_validate_config_mapping_missing_master(self):
method test_validate_config_mapping (line 1289) | def test_validate_config_mapping(self):
class TestConfigContainer (line 1302) | class TestConfigContainer(TestCase):
method setup_container (line 1306) | def setup_container(self):
method test_create (line 1314) | def test_create(self):
method test_create_missing_master (line 1323) | def test_create_missing_master(self):
method test_get_job_names (line 1331) | def test_get_job_names(self):
method test_get_jobs (line 1344) | def test_get_jobs(self):
method test_get_node_names (line 1356) | def test_get_node_names(self):
class TestValidateSSHOptions (line 1362) | class TestValidateSSHOptions(TestCase):
method setup_context (line 1364) | def setup_context(self):
method test_post_validation_failed (line 1369) | def test_post_validation_failed(self):
method test_post_validation_success (line 1380) | def test_post_validation_success(self):
class TestValidateIdentityFile (line 1389) | class TestValidateIdentityFile(TestCase):
method setup_context (line 1391) | def setup_context(self):
method test_valid_identity_file_missing_private_key (line 1395) | def test_valid_identity_file_missing_private_key(self):
method test_valid_identity_files_missing_public_key (line 1404) | def test_valid_identity_files_missing_public_key(self):
method test_valid_identity_files_valid (line 1414) | def test_valid_identity_files_valid(self):
method test_valid_identity_files_missing_with_partial_context (line 1424) | def test_valid_identity_files_missing_with_partial_context(self):
class TestValidKnownHostsFile (line 1431) | class TestValidKnownHostsFile(TestCase):
method setup_context (line 1433) | def setup_context(self):
method test_valid_known_hosts_file_exists (line 1437) | def test_valid_known_hosts_file_exists(self):
method test_valid_known_hosts_file_missing (line 1444) | def test_valid_known_hosts_file_missing(self):
method test_valid_known_hosts_file_missing_partial_context (line 1453) | def test_valid_known_hosts_file_missing_partial_context(self):
class TestValidateVolume (line 1463) | class TestValidateVolume(TestCase):
method setup_context (line 1465) | def setup_context(self):
method test_missing_container_path (line 1468) | def test_missing_container_path(self):
method test_missing_host_path (line 1481) | def test_missing_host_path(self):
method test_invalid_mode (line 1494) | def test_invalid_mode(self):
method test_valid (line 1507) | def test_valid(self):
method test_mesos_default_volumes (line 1518) | def test_mesos_default_volumes(self):
method test_k8s_default_volumes (line 1543) | def test_k8s_default_volumes(self):
class TestValidPermissionMode (line 1569) | class TestValidPermissionMode:
method test_valid_permissions (line 1574) | def test_valid_permissions(self, permission, normalized):
method test_invalid_permissions (line 1579) | def test_invalid_permissions(self, permission):
class TestValidSecretVolumeItem (line 1584) | class TestValidSecretVolumeItem:
method test_invalid (line 1600) | def test_invalid(self, config):
method test_valid_job_secret_volume_success (line 1608) | def test_valid_job_secret_volume_success(self, config):
method test_item_mode_propagation_and_override (line 1634) | def test_item_mode_propagation_and_override(self, item_config, default...
method test_volume_when_items_key_is_omitted (line 1653) | def test_volume_when_items_key_is_omitted(self):
method test_volume_when_items_is_empty (line 1666) | def test_volume_when_items_is_empty(self):
class TestValidSecretVolume (line 1683) | class TestValidSecretVolume:
method test_invalid (line 1717) | def test_invalid(self, config):
method test_wrong_item_key (line 1721) | def test_wrong_item_key(self):
method test_valid (line 1758) | def test_valid(self, config):
class TestValidMasterAddress (line 1762) | class TestValidMasterAddress:
method context (line 1764) | def context(self):
method test_valid (line 1776) | def test_valid(self, url, context):
method test_invalid (line 1791) | def test_invalid(self, url, context):
class TestValidKubeconfigPaths (line 1796) | class TestValidKubeconfigPaths:
method setup_context (line 1798) | def setup_context(self):
method test_valid (line 1805) | def test_valid(self, kubeconfig_path, watcher_kubeconfig_paths):
method test_invalid (line 1821) | def test_invalid(self, kubeconfig_path, watcher_kubeconfig_paths):
method test_nonretry (line 1830) | def test_nonretry(self):
class TestValidateStatePersistenceDefaults (line 1845) | class TestValidateStatePersistenceDefaults(TestCase):
method test_post_validation_sees_defaults_for_omitted_keys (line 1846) | def test_post_validation_sees_defaults_for_omitted_keys(self):
method test_post_validation_sees_provided_values (line 1886) | def test_post_validation_sees_provided_values(self):
FILE: tests/config/config_utils_test.py
class TestUniqueNameDict (line 18) | class TestUniqueNameDict(TestCase):
method setup_dict (line 20) | def setup_dict(self):
method test_set_item_no_conflict (line 24) | def test_set_item_no_conflict(self):
method test_set_item_conflict (line 28) | def test_set_item_conflict(self):
class TestValidatorIdentifier (line 33) | class TestValidatorIdentifier(TestCase):
method test_valid_identifier_too_long (line 34) | def test_valid_identifier_too_long(self):
method test_valid_identifier (line 37) | def test_valid_identifier(self):
method test_valid_identifier_invalid_character (line 41) | def test_valid_identifier_invalid_character(self):
class TestBuildListOfTypeValidator (line 46) | class TestBuildListOfTypeValidator(TestCase):
method setup_validator (line 48) | def setup_validator(self):
method test_validator_passes (line 52) | def test_validator_passes(self):
method test_validator_fails (line 58) | def test_validator_fails(self):
class TestBuildEnumValidator (line 64) | class TestBuildEnumValidator(TestCase):
method setup_enum_validator (line 66) | def setup_enum_validator(self):
method test_validate (line 71) | def test_validate(self):
method test_invalid (line 75) | def test_invalid(self):
class TestValidTime (line 88) | class TestValidTime(TestCase):
method setup_config (line 90) | def setup_config(self):
method test_valid_time (line 93) | def test_valid_time(self):
method test_valid_time_with_seconds (line 99) | def test_valid_time_with_seconds(self):
method test_valid_time_invalid (line 105) | def test_valid_time_invalid(self):
class TestValidTimeDelta (line 115) | class TestValidTimeDelta(TestCase):
method setup_config (line 117) | def setup_config(self):
method test_valid_time_delta_invalid (line 120) | def test_valid_time_delta_invalid(self):
method test_valid_time_delta_valid_seconds (line 129) | def test_valid_time_delta_valid_seconds(self):
method test_valid_time_delta_valid_minutes (line 140) | def test_valid_time_delta_valid_minutes(self):
method test_valid_time_delta_invalid_unit (line 151) | def test_valid_time_delta_invalid_unit(self):
class TestConfigContext (line 161) | class TestConfigContext(TestCase):
method test_build_config_context (line 162) | def test_build_config_context(self):
class StubValidator (line 187) | class StubValidator(config_utils.Validator):
class TestValidator (line 191) | class TestValidator(TestCase):
method setup_validator (line 193) | def setup_validator(self):
method test_validate_with_none (line 196) | def test_validate_with_none(self):
method test_validate_optional_with_none (line 206) | def test_validate_optional_with_none(self):
FILE: tests/config/manager_test.py
class TestFromString (line 19) | class TestFromString(TestCase):
method test_from_string_valid (line 20) | def test_from_string_valid(self):
method test_from_string_invalid (line 26) | def test_from_string_invalid(self):
class TestReadWrite (line 31) | class TestReadWrite(TestCase):
method setup_tempfile (line 33) | def setup_tempfile(self):
method teardown_tempfile (line 37) | def teardown_tempfile(self):
method test_read_write (line 40) | def test_read_write(self):
method test_read_raw_write_raw (line 46) | def test_read_raw_write_raw(self):
class TestManifestFile (line 53) | class TestManifestFile(TestCase):
method setup_manifest (line 55) | def setup_manifest(self):
method teardown_dir (line 61) | def teardown_dir(self):
method test_create_exists (line 66) | def test_create_exists(self, mock_write, mock_os):
method test_create (line 71) | def test_create(self):
method test_add (line 74) | def test_add(self):
method test_delete (line 79) | def test_delete(self):
method test_get_file_mapping (line 89) | def test_get_file_mapping(self):
class TestConfigManager (line 98) | class TestConfigManager(TestCase):
method setup_config_manager (line 104) | def setup_config_manager(self):
method teardown_dir (line 111) | def teardown_dir(self):
method test_build_file_path (line 114) | def test_build_file_path(self):
method test_build_file_path_with_invalid_chars (line 118) | def test_build_file_path_with_invalid_chars(self):
method test_read_raw_config (line 130) | def test_read_raw_config(self):
method test_write_config (line 138) | def test_write_config(self):
method test_write_config_new_name (line 153) | def test_write_config_new_name(self):
method test_delete_config (line 164) | def test_delete_config(self, mock_remove):
method test_delete_missing_namespace (line 173) | def test_delete_missing_namespace(self, mock_remove):
method test_validate_with_fragment (line 187) | def test_validate_with_fragment(self, mock_config_container, mock_job_...
method test_load (line 206) | def test_load(self, mock_config_container, mock_read):
method test_get_hash_default (line 216) | def test_get_hash_default(self):
method test_get_hash (line 221) | def test_get_hash(self):
class TestCreateNewConfig (line 229) | class TestCreateNewConfig(TestCase):
method test_create_new_config (line 233) | def test_create_new_config(self, mock_write, mock_manifest, mock_maked...
FILE: tests/config/schedule_parse_test.py
class TestPadSequence (line 13) | class TestPadSequence(TestCase):
method test_pad_sequence_short (line 14) | def test_pad_sequence_short(self):
method test_pad_sequence_long (line 18) | def test_pad_sequence_long(self):
method test_pad_sequence_exact (line 22) | def test_pad_sequence_exact(self):
method test_pad_sequence_empty (line 26) | def test_pad_sequence_empty(self):
method test_pad_negative_size (line 30) | def test_pad_negative_size(self):
class TestScheduleConfigFromString (line 34) | class TestScheduleConfigFromString(TestCase):
method test_groc_config (line 39) | def test_groc_config(self, mock_parse_groc):
class TestValidScheduler (line 52) | class TestValidScheduler(TestCase):
method assert_validation (line 54) | def assert_validation(self, schedule, expected, mock_schedulers):
method test_cron_from_dict (line 62) | def test_cron_from_dict(self):
method test_cron_from_dict_with_jitter (line 71) | def test_cron_from_dict_with_jitter(self):
class TestValidCronScheduler (line 81) | class TestValidCronScheduler(TestCase):
method validate (line 84) | def validate(self, line):
method test_valid_config (line 89) | def test_valid_config(self):
method test_invalid_config (line 95) | def test_invalid_config(self):
class TestValidDailyScheduler (line 99) | class TestValidDailyScheduler(TestCase):
method validate (line 100) | def validate(self, config):
method assert_parse (line 105) | def assert_parse(self, config, expected):
method test_valid_daily_scheduler_start_time (line 110) | def test_valid_daily_scheduler_start_time(self):
method test_valid_daily_scheduler_just_days (line 114) | def test_valid_daily_scheduler_just_days(self):
method test_valid_daily_scheduler_time_and_day (line 118) | def test_valid_daily_scheduler_time_and_day(self):
method test_valid_daily_scheduler_invalid_start_time (line 122) | def test_valid_daily_scheduler_invalid_start_time(self):
method test_valid_daily_scheduler_invalid_days (line 127) | def test_valid_daily_scheduler_invalid_days(self):
FILE: tests/core/action_test.py
class TestAction (line 18) | class TestAction:
method test_from_config_full (line 20) | def test_from_config_full(self, disk):
method test_from_config_none_values (line 85) | def test_from_config_none_values(self):
method action_command_config_json (line 106) | def action_command_config_json(self):
method test_action_command_config_from_json (line 199) | def test_action_command_config_from_json(self, action_command_config_j...
FILE: tests/core/actiongraph_test.py
class TestActionGraph (line 11) | class TestActionGraph(TestCase):
method setup_graph (line 13) | def setup_graph(self):
method test_get_dependencies (line 43) | def test_get_dependencies(self):
method test_names (line 54) | def test_names(self):
method test__getitem__ (line 60) | def test__getitem__(self):
method test__getitem__miss (line 66) | def test__getitem__miss(self):
method test__eq__ (line 69) | def test__eq__(self):
method test__ne__ (line 80) | def test__ne__(self):
FILE: tests/core/actionrun_test.py
function output_path (line 37) | def output_path():
function mock_current_time (line 44) | def mock_current_time():
class TestMinFilter (line 52) | class TestMinFilter:
method test_min_filter (line 53) | def test_min_filter(self):
class TestEagerAll (line 58) | class TestEagerAll:
method test_all_true (line 59) | def test_all_true(self):
method test_all_false (line 62) | def test_all_false(self):
method test_full_iteration (line 65) | def test_full_iteration(self):
class TestActionRunFactory (line 72) | class TestActionRunFactory:
method setup_action_runs (line 74) | def setup_action_runs(self):
method state_data (line 102) | def state_data(self):
method test_build_action_run_collection (line 116) | def test_build_action_run_collection(self):
method test_action_run_collection_from_state (line 127) | def test_action_run_collection_from_state(self, state_data):
method test_build_run_for_action (line 163) | def test_build_run_for_action(self):
method test_build_run_for_action_with_node (line 183) | def test_build_run_for_action_with_node(self):
method test_build_run_for_ssh_action (line 203) | def test_build_run_for_ssh_action(self):
method test_build_run_for_mesos_action (line 216) | def test_build_run_for_mesos_action(self):
method test_action_run_from_state_ssh (line 257) | def test_action_run_from_state_ssh(self, state_data):
method test_action_run_from_state_mesos (line 267) | def test_action_run_from_state_mesos(self, state_data):
method test_action_run_from_state_kubernetes (line 281) | def test_action_run_from_state_kubernetes(self, state_data):
method test_action_run_from_state_spark (line 295) | def test_action_run_from_state_spark(self, state_data):
class TestActionRun (line 310) | class TestActionRun:
method setup_action_run (line 312) | def setup_action_run(self, output_path):
method test_init_state (line 329) | def test_init_state(self):
method test_ready_state (line 332) | def test_ready_state(self):
method test_start (line 336) | def test_start(self):
method test_start_bad_state (line 343) | def test_start_bad_state(self):
method test_start_invalid_command (line 348) | def test_start_invalid_command(self, _log):
method test_success (line 355) | def test_success(self):
method test_success_emits_not (line 367) | def test_success_emits_not(self):
method test_sucess_emits_not_invalid_transition (line 375) | def test_sucess_emits_not_invalid_transition(self):
method test_success_emits_on_true (line 383) | def test_success_emits_on_true(self):
method test_success_emits_on_dict (line 391) | def test_success_emits_on_dict(self):
method test_emit_triggers (line 400) | def test_emit_triggers(self, eventbus):
method test_failure (line 414) | def test_failure(self):
method test_failure_bad_state (line 421) | def test_failure_bad_state(self):
method test_skip (line 426) | def test_skip(self):
method test_skip_bad_state (line 435) | def test_skip_bad_state(self):
method test_render_command (line 438) | def test_render_command(self):
method test_command_not_yet_rendered (line 443) | def test_command_not_yet_rendered(self):
method test_command_already_rendered (line 446) | def test_command_already_rendered(self):
method test_command_failed_render (line 451) | def test_command_failed_render(self, _log):
method test_is_complete (line 455) | def test_is_complete(self):
method test_is_broken (line 463) | def test_is_broken(self):
method test__getattr__ (line 471) | def test__getattr__(self):
method test__getattr__missing_attribute (line 479) | def test__getattr__missing_attribute(self):
method test_auto_retry (line 483) | def test_auto_retry(self, mock_current_time):
method test_auto_retry_command_config_change (line 508) | def test_auto_retry_command_config_change(self, mock_current_time):
method test_no_auto_retry_on_fail_not_running (line 524) | def test_no_auto_retry_on_fail_not_running(self):
method test_no_auto_retry_on_fail_running (line 534) | def test_no_auto_retry_on_fail_running(self):
method test_auto_retry_already_done (line 546) | def test_auto_retry_already_done(self):
method test_manual_retry (line 566) | def test_manual_retry(self, mock_current_time):
method test_manual_retry_use_new_command (line 583) | def test_manual_retry_use_new_command(self, mock_current_time):
method test_retries_delay (line 597) | def test_retries_delay(self, callLater):
class TestActionRunFactoryTriggerTimeout (line 606) | class TestActionRunFactoryTriggerTimeout:
method test_trigger_timeout_default (line 607) | def test_trigger_timeout_default(self):
method test_trigger_timeout_custom (line 618) | def test_trigger_timeout_custom(self):
class TestActionRunTriggerTimeout (line 630) | class TestActionRunTriggerTimeout:
method setup_teardown (line 632) | def setup_teardown(self):
method test_cleanup_clears_trigger_timeout (line 649) | def test_cleanup_clears_trigger_timeout(self):
method test_clear_trigger_timeout (line 654) | def test_clear_trigger_timeout(self):
method test_setup_subscriptions_no_triggers (line 663) | def test_setup_subscriptions_no_triggers(self, reactor, eventbus):
method test_setup_subscriptions_no_remaining (line 671) | def test_setup_subscriptions_no_remaining(self, reactor, eventbus):
method test_setup_subscriptions_timeout_in_future (line 681) | def test_setup_subscriptions_timeout_in_future(self, reactor, mock_cur...
method test_setup_subscriptions_timeout_in_past (line 692) | def test_setup_subscriptions_timeout_in_past(self, reactor, mock_curre...
method test_trigger_timeout_reached_no_remaining_notifies (line 703) | def test_trigger_timeout_reached_no_remaining_notifies(self, eventbus):
method test_trigger_timeout_reached_with_remaining_fails (line 711) | def test_trigger_timeout_reached_with_remaining_fails(self, eventbus):
method test_done_clears_trigger_timeout_call (line 718) | def test_done_clears_trigger_timeout_call(self):
method test_trigger_notify_clears_trigger_timeout (line 726) | def test_trigger_notify_clears_trigger_timeout(self):
class TestSSHActionRun (line 734) | class TestSSHActionRun:
method setup_action_run (line 736) | def setup_action_run(self, output_path):
method test_start_node_error (line 750) | def test_start_node_error(self):
method test_build_action_command (line 762) | def test_build_action_command(self, mock_filehandler):
method test_handler_running (line 779) | def test_handler_running(self):
method test_handler_failstart (line 789) | def test_handler_failstart(self):
method test_handler_exiting_fail (line 798) | def test_handler_exiting_fail(self):
method test_handler_exiting_success (line 810) | def test_handler_exiting_success(self):
method test_handler_exiting_failunknown (line 823) | def test_handler_exiting_failunknown(self):
method test_handler_unhandled (line 838) | def test_handler_unhandled(self):
method test_recover_no_action_runner (line 850) | def test_recover_no_action_runner(self):
class TestSSHActionRunRecover (line 855) | class TestSSHActionRunRecover:
method setup_action_run (line 857) | def setup_action_run(self, output_path):
method test_recover_incorrect_state (line 872) | def test_recover_incorrect_state(self):
method test_recover_action_runner (line 877) | def test_recover_action_runner(self):
method test_handler_exiting_failunknown (line 900) | def test_handler_exiting_failunknown(self, mock_reactor):
method test_handler_exiting_failunknown_max_retries (line 934) | def test_handler_exiting_failunknown_max_retries(self, mock_reactor, m...
class TestActionRunStateRestore (line 964) | class TestActionRunStateRestore:
method setup_action_run (line 968) | def setup_action_run(self, mock_current_time):
method state_data (line 985) | def state_data(self):
method state_data_old (line 1008) | def state_data_old(self):
method test_from_state_old (line 1020) | def test_from_state_old(self, state_data_old):
method test_from_state_old_with_mesos_task_id (line 1041) | def test_from_state_old_with_mesos_task_id(self, state_data_old):
method test_from_state_old_not_started (line 1060) | def test_from_state_old_not_started(self, state_data_old):
method test_from_state_old_rendered_and_exited (line 1081) | def test_from_state_old_rendered_and_exited(self, state_data_old):
method test_from_state_old_retries (line 1103) | def test_from_state_old_retries(self, state_data_old):
method test_from_state_running (line 1131) | def test_from_state_running(self, state_data):
method test_from_state_starting (line 1143) | def test_from_state_starting(self, state_data):
method test_from_state_queued (line 1155) | def test_from_state_queued(self, state_data):
method test_from_state_no_node_name (line 1167) | def test_from_state_no_node_name(self, state_data):
method test_from_state_with_node_exists (line 1180) | def test_from_state_with_node_exists(self, mock_store, state_data):
method test_from_state_after_rendered_command (line 1194) | def test_from_state_after_rendered_command(self, state_data):
method test_from_state_action_config_gone (line 1208) | def test_from_state_action_config_gone(self, state_data):
class TestActionRunCollection (line 1222) | class TestActionRunCollection:
method _build_run (line 1223) | def _build_run(self, action):
method setup_runs (line 1234) | def setup_runs(self, output_path):
method test__init__ (line 1259) | def test__init__(self):
method test_action_runs_for_actions (line 1264) | def test_action_runs_for_actions(self):
method test_get_action_runs_with_cleanup (line 1271) | def test_get_action_runs_with_cleanup(self):
method test_get_action_runs (line 1275) | def test_get_action_runs(self):
method test_cleanup_action_run (line 1279) | def test_cleanup_action_run(self):
method test_update_action_config_no_changes (line 1282) | def test_update_action_config_no_changes(self):
method test_update_action_config (line 1285) | def test_update_action_config(self):
method test_state_data (line 1316) | def test_state_data(self):
method test_cleanup_action_state_data (line 1320) | def test_cleanup_action_state_data(self):
method test_cleanup_action_state_data_no_cleanup_action (line 1324) | def test_cleanup_action_state_data_no_cleanup_action(self):
method test_get_startable_action_runs (line 1328) | def test_get_startable_action_runs(self):
method test_get_startable_action_runs_none (line 1332) | def test_get_startable_action_runs_none(self):
method test_has_startable_action_runs (line 1337) | def test_has_startable_action_runs(self):
method test_has_startable_action_runs_false (line 1340) | def test_has_startable_action_runs_false(self):
method test_is_complete_false (line 1344) | def test_is_complete_false(self):
method test_is_complete_true (line 1347) | def test_is_complete_true(self):
method test_is_done_false (line 1352) | def test_is_done_false(self):
method test_is_done_false_because_of_running (line 1355) | def test_is_done_false_because_of_running(self):
method test_is_done_true_because_blocked (line 1360) | def test_is_done_true_because_blocked(self):
method test_is_done_true (line 1373) | def test_is_done_true(self):
method test_is_failed_false_not_done (line 1378) | def test_is_failed_false_not_done(self):
method test_is_failed_false_no_failed (line 1382) | def test_is_failed_false_no_failed(self):
method test_is_failed_true (line 1387) | def test_is_failed_true(self):
method test__getattr__ (line 1392) | def test__getattr__(self):
method test__str__ (line 1398) | def test__str__(self):
method test_end_time (line 1409) | def test_end_time(self):
method test_end_time_not_done (line 1417) | def test_end_time_not_done(self):
method test_end_time_not_started (line 1424) | def test_end_time_not_started(self):
class TestActionRunCollectionIsRunBlocked (line 1428) | class TestActionRunCollectionIsRunBlocked:
method _build_run (line 1429) | def _build_run(self, name):
method setup_collection (line 1440) | def setup_collection(self, output_path):
method test_is_run_blocked_no_required_actions (line 1464) | def test_is_run_blocked_no_required_actions(self):
method test_is_run_blocked_completed_run (line 1467) | def test_is_run_blocked_completed_run(self):
method test_is_run_blocked_required_actions_completed (line 1474) | def test_is_run_blocked_required_actions_completed(self):
method test_is_run_blocked_required_actions_blocked (line 1478) | def test_is_run_blocked_required_actions_blocked(self):
method test_is_run_blocked_required_actions_scheduled (line 1488) | def test_is_run_blocked_required_actions_scheduled(self):
method test_is_run_blocked_required_actions_starting (line 1492) | def test_is_run_blocked_required_actions_starting(self):
method test_is_run_blocked_required_actions_waiting (line 1496) | def test_is_run_blocked_required_actions_waiting(self):
method test_is_run_blocked_required_actions_failed (line 1500) | def test_is_run_blocked_required_actions_failed(self):
method test_is_run_blocked_required_actions_missing (line 1504) | def test_is_run_blocked_required_actions_missing(self):
method test_is_run_blocked_in_job_only (line 1508) | def test_is_run_blocked_in_job_only(self):
class TestMesosActionRun (line 1515) | class TestMesosActionRun:
method setup_action_run (line 1517) | def setup_action_run(self):
method test_submit_command (line 1554) | def test_submit_command(self, mock_cluster_repo, mock_filehandler):
method test_submit_command_task_none (line 1596) | def test_submit_command_task_none(
method test_recover (line 1613) | def test_recover(self, mock_cluster_repo, mock_filehandler):
method test_recover_done_no_change (line 1656) | def test_recover_done_no_change(self, mock_cluster_repo, mock_filehand...
method test_recover_no_mesos_task_id (line 1667) | def test_recover_no_mesos_task_id(
method test_recover_task_none (line 1683) | def test_recover_task_none(self, mock_cluster_repo, mock_filehandler):
method test_kill_task (line 1698) | def test_kill_task(self, mock_cluster_repo):
method test_kill_task_no_task_id (line 1710) | def test_kill_task_no_task_id(self, mock_cluster_repo):
method test_stop_task (line 1717) | def test_stop_task(self, mock_cluster_repo):
method test_stop_task_no_task_id (line 1729) | def test_stop_task_no_task_id(self, mock_cluster_repo):
method test_handler_exiting_unknown (line 1735) | def test_handler_exiting_unknown(self):
method test_handler_exiting_unknown_retry (line 1750) | def test_handler_exiting_unknown_retry(self):
method test_handler_exiting_failstart_failed (line 1768) | def test_handler_exiting_failstart_failed(self):
class TestKubernetesActionRun (line 1781) | class TestKubernetesActionRun:
method mock_k8s_action_run (line 1783) | def mock_k8s_action_run(self):
method test_k8s_handler_exiting_unknown (line 1814) | def test_k8s_handler_exiting_unknown(self, mock_k8s_action_run):
method test_handler_exiting_unknown_retry (line 1829) | def test_handler_exiting_unknown_retry(self, mock_k8s_action_run):
method test_handler_exiting_failstart_failed (line 1847) | def test_handler_exiting_failstart_failed(self, mock_k8s_action_run):
method test_recover (line 1861) | def test_recover(self, mock_cluster_repo, mock_filehandler, mock_k8s_a...
method test_recover_done_no_change (line 1922) | def test_recover_done_no_change(
method test_recover_no_k8s_task_id (line 1938) | def test_recover_no_k8s_task_id(
method test_recover_task_none (line 1955) | def test_recover_task_none(self, mock_cluster_repo, mock_filehandler, ...
method test_kill_task_k8s (line 1970) | def test_kill_task_k8s(self, mock_cluster_repo, mock_k8s_action_run):
method test_kill_task_no_task_id_k8s (line 1980) | def test_kill_task_no_task_id_k8s(self, mock_cluster_repo, mock_k8s_ac...
method test_stop_task_k8s (line 1987) | def test_stop_task_k8s(self, mock_cluster_repo, mock_k8s_action_run):
method test_stop_task_no_task_id_k8s (line 1997) | def test_stop_task_no_task_id_k8s(self, mock_cluster_repo, mock_k8s_ac...
method test_non_retryable_exit (line 2004) | def test_non_retryable_exit(self, mock_cluster_repo, mock_k8s_action_r...
method test_retryable_exit (line 2027) | def test_retryable_exit(self, mock_cluster_repo, mock_k8s_action_run):
method test_submit_command_first_attempt_labels (line 2043) | def test_submit_command_first_attempt_labels(self, mock_cluster_repo, ...
method test_submit_command_retry_attempt_labels (line 2053) | def test_submit_command_retry_attempt_labels(self, mock_cluster_repo, ...
method test_recover_retry_attempt_labels (line 2073) | def test_recover_retry_attempt_labels(self, mock_cluster_repo, mock_fi...
FILE: tests/core/job_collection_test.py
class TestJobCollection (line 12) | class TestJobCollection(TestCase):
method setup_collection (line 14) | def setup_collection(self):
method test_update_from_config (line 17) | def test_update_from_config(self):
method test_update_from_config_reconfigure_one_namespace (line 34) | def test_update_from_config_reconfigure_one_namespace(self):
method test_move_running_job (line 54) | def test_move_running_job(self):
method test_move (line 63) | def test_move(self):
method test_update (line 74) | def test_update(self):
FILE: tests/core/job_scheduler_test.py
class TestJobSchedulerGetRunsToSchedule (line 16) | class TestJobSchedulerGetRunsToSchedule(TestCase):
method setup_job (line 18) | def setup_job(self):
method test_get_runs_to_schedule_with_pending (line 32) | def test_get_runs_to_schedule_with_pending(self):
method test_get_runs_to_schedule_guess (line 38) | def test_get_runs_to_schedule_guess(self):
method test_get_runs_to_schedule_given (line 46) | def test_get_runs_to_schedule_given(self):
class JobSchedulerManualStartTestCase (line 56) | class JobSchedulerManualStartTestCase(testingutils.MockTimeTestCase):
method setup_job (line 61) | def setup_job(self):
method test_manual_start (line 75) | def test_manual_start(self):
method test_manual_start_default_with_timezone (line 82) | def test_manual_start_default_with_timezone(self):
method test_manual_start_with_run_time (line 97) | def test_manual_start_with_run_time(self):
class TestJobSchedulerSchedule (line 106) | class TestJobSchedulerSchedule(TestCase):
method setup_job (line 108) | def setup_job(self):
method test_enable (line 133) | def test_enable(self, reactor):
method test_enable_noop (line 140) | def test_enable_noop(self, reactor):
method test_schedule (line 147) | def test_schedule(self, reactor):
method test_schedule_disabled_job (line 163) | def test_schedule_disabled_job(self, reactor):
method test_handle_job_events_no_schedule_on_complete (line 169) | def test_handle_job_events_no_schedule_on_complete(self, reactor):
method test_handle_job_events_schedule_on_complete (line 182) | def test_handle_job_events_schedule_on_complete(self):
method test_handler_unknown_event (line 188) | def test_handler_unknown_event(self):
method test_handler_no_queued (line 193) | def test_handler_no_queued(self):
method test_run_queue_schedule (line 205) | def test_run_queue_schedule(self, reactor):
class TestJobSchedulerOther (line 224) | class TestJobSchedulerOther(TestCase):
method _make_job_scheduler (line 227) | def _make_job_scheduler(self, job_name, enabled=True):
method setup_job (line 241) | def setup_job(self):
method test_disable (line 247) | def test_disable(self):
method test_update_from_job_scheduler_disable (line 255) | def test_update_from_job_scheduler_disable(self):
method test_update_from_job_scheduler_enable (line 267) | def test_update_from_job_scheduler_enable(self):
method test_update_from_job_scheduler_no_config_change (line 281) | def test_update_from_job_scheduler_no_config_change(self):
class TestJobSchedulerFactory (line 299) | class TestJobSchedulerFactory(TestCase):
method setup_factory (line 301) | def setup_factory(self):
method test_build (line 316) | def test_build(self):
FILE: tests/core/job_test.py
function mock_node_repo (line 22) | def mock_node_repo():
function mock_job (line 31) | def mock_job(mock_node_repo):
class TestJob (line 47) | class TestJob:
method setup_job (line 49) | def setup_job(self, mock_job):
method test__init__ (line 55) | def test__init__(self):
method test_from_config (line 58) | def test_from_config(self, mock_node_repo):
method test_update_from_job (line 103) | def test_update_from_job(self):
method test_status_disabled (line 117) | def test_status_disabled(self):
method test_status_enabled (line 121) | def test_status_enabled(self):
method test_status_running (line 126) | def test_status_running(self):
method test_status_unknown (line 130) | def test_status_unknown(self):
method test_state_data (line 135) | def test_state_data(self):
method test_get_job_runs_from_state (line 140) | def test_get_job_runs_from_state(self):
method test_build_new_runs (line 157) | def test_build_new_runs(self):
method test_build_new_runs_all_nodes (line 174) | def test_build_new_runs_all_nodes(self):
method test_build_new_runs_manual (line 198) | def test_build_new_runs_manual(self):
method test_handler (line 215) | def test_handler(self):
method test__eq__ (line 222) | def test__eq__(self):
method test__ne__ (line 228) | def test__ne__(self):
method test__eq__true (line 234) | def test__eq__true(self):
method test__eq__false (line 240) | def test__eq__false(self):
function test_job_watch_notifies_about_runs (line 246) | def test_job_watch_notifies_about_runs(mock_job):
class TestJobScheduler (line 270) | class TestJobScheduler:
method setup_job (line 272) | def setup_job(self):
method test_restore_state_sets_job_runs (line 281) | def test_restore_state_sets_job_runs(self):
method test_create_and_schedule_runs_specific_time (line 310) | def test_create_and_schedule_runs_specific_time(self):
method test_create_and_schedule_runs_guess (line 316) | def test_create_and_schedule_runs_guess(self):
method test_disable (line 322) | def test_disable(self):
method test_schedule_reconfigured (line 327) | def test_schedule_reconfigured(self):
method test_schedule (line 342) | def test_schedule(self):
method test_run_job (line 356) | def test_run_job(self):
method test_run_job_job_disabled (line 366) | def test_run_job_job_disabled(self):
method test_run_job_cancelled (line 375) | def test_run_job_cancelled(self):
method test_run_job_already_running_queuing (line 382) | def test_run_job_already_running_queuing(self):
method test_run_job_already_running_cancel (line 392) | def test_run_job_already_running_cancel(self):
method test_run_job_already_running_allow_overlap (line 403) | def test_run_job_already_running_allow_overlap(self):
method test_run_job_has_starting_queueing (line 411) | def test_run_job_has_starting_queueing(self):
method test_run_job_schedule_on_complete (line 421) | def test_run_job_schedule_on_complete(self):
FILE: tests/core/jobgraph_test.py
function _setup_job_graph_config_container (line 17) | def _setup_job_graph_config_container():
class TestJobGraph (line 74) | class TestJobGraph:
method setup_method (line 75) | def setup_method(self):
method test_job_graph_missing_dependency (line 78) | def test_job_graph_missing_dependency(self):
method test_job_graph (line 88) | def test_job_graph(self):
method test_get_action_graph_for_job (line 118) | def test_get_action_graph_for_job(self):
FILE: tests/core/jobrun_test.py
function build_mock_job (line 27) | def build_mock_job():
class TestJobRun (line 45) | class TestJobRun:
method setup_jobrun (line 51) | def setup_jobrun(self):
method test__init__ (line 73) | def test__init__(self):
method test_for_job (line 78) | def test_for_job(self):
method test_for_job_manual (line 95) | def test_for_job_manual(self):
method test_state_data (line 108) | def test_state_data(self):
method test_set_action_runs (line 114) | def test_set_action_runs(self):
method test_set_action_runs_none (line 130) | def test_set_action_runs_none(self):
method test_set_action_runs_duplicate (line 137) | def test_set_action_runs_duplicate(self):
method test_seconds_until_run_time (line 146) | def test_seconds_until_run_time(self, mock_current_time):
method test_seconds_until_run_time_with_tz (line 152) | def test_seconds_until_run_time_with_tz(self, mock_current_time):
method test_start (line 158) | def test_start(self):
method test_start_failed (line 163) | def test_start_failed(self):
method test_do_start (line 167) | def test_do_start(self):
method test_do_start_all_failed (line 176) | def test_do_start_all_failed(self):
method test_do_start_some_failed (line 180) | def test_do_start_some_failed(self):
method test_do_start_no_runs (line 185) | def test_do_start_no_runs(self):
method test_start_action_runs (line 188) | def test_start_action_runs(self):
method test_start_action_runs_failed (line 195) | def test_start_action_runs_failed(self):
method jobrun_json (line 204) | def jobrun_json(self):
method test_from_json (line 260) | def test_from_json(self, jobrun_json):
method test_start_action_runs_all_failed (line 312) | def test_start_action_runs_all_failed(self):
method test_handler_trigger_ready_still_scheduled (line 321) | def test_handler_trigger_ready_still_scheduled(self):
method test_handler_trigger_ready_started (line 327) | def test_handler_trigger_ready_started(self):
method test_handler_not_end_state_event (line 334) | def test_handler_not_end_state_event(self):
method test_handler_with_startable (line 342) | def test_handler_with_startable(self):
method test_handler_runs_not_done (line 357) | def test_handler_runs_not_done(self):
method test_handler_finished_without_cleanup (line 364) | def test_handler_finished_without_cleanup(self):
method test_handler_finished_with_cleanup_done (line 372) | def test_handler_finished_with_cleanup_done(self):
method test_handler_finished_with_cleanup (line 380) | def test_handler_finished_with_cleanup(self):
method test_handler_action_run_cancelled (line 389) | def test_handler_action_run_cancelled(self):
method test_handler_action_run_skipped (line 395) | def test_handler_action_run_skipped(self):
method test_state (line 403) | def test_state(self):
method test_state_with_no_action_runs (line 406) | def test_state_with_no_action_runs(self):
method test_finalize (line 410) | def test_finalize(self):
method test_finalize_failure (line 415) | def test_finalize_failure(self):
method test_cleanup (line 419) | def test_cleanup(self):
method test__getattr__ (line 431) | def test__getattr__(self):
method test__getattr__miss (line 436) | def test__getattr__miss(self):
class TestJobRunFromState (line 440) | class TestJobRunFromState(TestCase):
method setup_jobrun (line 442) | def setup_jobrun(self):
method test_from_state (line 473) | def test_from_state(self):
method test_from_state_node_no_longer_exists (line 489) | def test_from_state_node_no_longer_exists(self):
class MockJobRun (line 503) | class MockJobRun(MagicMock):
method is_scheduled (line 510) | def is_scheduled(self):
method is_queued (line 514) | def is_queued(self):
method is_running (line 518) | def is_running(self):
method is_starting (line 522) | def is_starting(self):
method is_waiting (line 526) | def is_waiting(self):
method __repr__ (line 529) | def __repr__(self):
class TestJobRunCollection (line 533) | class TestJobRunCollection(TestCase):
method _mock_run (line 534) | def _mock_run(self, **kwargs):
method setup_runs (line 538) | def setup_runs(self):
method test__init__ (line 554) | def test__init__(self):
method test_from_config (line 557) | def test_from_config(self):
method test_job_runs_from_state (line 562) | def test_job_runs_from_state(self):
method test_build_new_run (line 589) | def test_build_new_run(self):
method test_build_new_run_manual (line 603) | def test_build_new_run_manual(self):
method test_cancel_pending (line 618) | def test_cancel_pending(self):
method test_cancel_pending_no_pending (line 628) | def test_cancel_pending_no_pending(self):
method test_remove_pending (line 632) | def test_remove_pending(self):
method test_get_run_by_state (line 638) | def test_get_run_by_state(self):
method test_get_run_by_state_no_match (line 643) | def test_get_run_by_state_no_match(self):
method test_get_run_by_num (line 648) | def test_get_run_by_num(self):
method test_get_run_by_num_no_match (line 652) | def test_get_run_by_num_no_match(self):
method test_get_run_by_index (line 656) | def test_get_run_by_index(self):
method test_get_run_by_index_invalid_index (line 666) | def test_get_run_by_index_invalid_index(self):
method test_get_newest (line 672) | def test_get_newest(self):
method test_get_newest_exclude_manual (line 676) | def test_get_newest_exclude_manual(self):
method test_get_newest_no_runs (line 686) | def test_get_newest_no_runs(self):
method test_pending (line 690) | def test_pending(self):
method test_get_active (line 701) | def test_get_active(self):
method test_get_active_with_node (line 711) | def test_get_active_with_node(self):
method test_get_active_none (line 722) | def test_get_active_none(self):
method test_get_first_queued (line 726) | def test_get_first_queued(self):
method test_get_first_queued_no_match (line 737) | def test_get_first_queued_no_match(self):
method test_get_next_run_num (line 742) | def test_get_next_run_num(self):
method test_get_next_run_num_first (line 745) | def test_get_next_run_num_first(self):
method test_remove_old_runs (line 749) | def test_remove_old_runs(self):
method test_remove_old_runs_none (line 758) | def test_remove_old_runs_none(self):
method test_remove_old_runs_no_runs (line 763) | def test_remove_old_runs_no_runs(self):
method test_state_data (line 767) | def test_state_data(self):
method test_last_success (line 770) | def test_last_success(self):
method test__str__ (line 773) | def test__str__(self):
method test_get_action_runs (line 777) | def test_get_action_runs(self):
method test_get_run_nums (line 786) | def test_get_run_nums(self):
class TestJobRunStateTransitions (line 790) | class TestJobRunStateTransitions:
method mock_event_bus (line 794) | def mock_event_bus(self):
method job_run (line 803) | def job_run(self, tmpdir, mock_event_bus):
method test_success_path (line 830) | def test_success_path(self, job_run):
method test_one_action_fails (line 865) | def test_one_action_fails(self, job_run):
method test_one_action_unknown (line 891) | def test_one_action_unknown(self, job_run):
method test_both_unknown_and_failed (line 915) | def test_both_unknown_and_failed(self, job_run):
method test_required_action_fails (line 938) | def test_required_action_fails(self, job_run):
method test_required_action_unknown (line 966) | def test_required_action_unknown(self, job_run):
method test_with_trigger (line 991) | def test_with_trigger(self, job_run, mock_event_bus):
method test_queued (line 1029) | def test_queued(self, job_run):
method test_cancel_one (line 1036) | def test_cancel_one(self, job_run):
FILE: tests/core/recovery_test.py
class TestRecovery (line 17) | class TestRecovery(TestCase):
method fake_action_runs (line 19) | def fake_action_runs(self):
method test_filter_action_runs_needing_recovery (line 82) | def test_filter_action_runs_needing_recovery(self):
method test_launch_recovery_actionruns_for_job_runs (line 90) | def test_launch_recovery_actionruns_for_job_runs(self, mock_filter):
method test_launch_recovery_actionruns_empty_job_run (line 138) | def test_launch_recovery_actionruns_empty_job_run(self, mock_filter):
FILE: tests/eventbus_test.py
class MakeEventBusTestCase (line 13) | class MakeEventBusTestCase(TestCase):
method setup (line 15) | def setup(self):
method teardown (line 19) | def teardown(self):
method test_setup_eventbus_dir (line 24) | def test_setup_eventbus_dir(self, time):
class EventBusTestCase (line 41) | class EventBusTestCase(TestCase):
method setup (line 43) | def setup(self):
method teardown (line 49) | def teardown(self):
method test_start (line 54) | def test_start(self, reactor):
method test_shutdown (line 61) | def test_shutdown(self):
method test_publish (line 68) | def test_publish(self):
method test_subscribe (line 73) | def test_subscribe(self):
method test_has_event (line 78) | def test_has_event(self):
method test_sync_load_log (line 84) | def test_sync_load_log(self, time):
method test_sync_save_log_time (line 93) | def test_sync_save_log_time(self, time):
method test_sync_loop (line 111) | def test_sync_loop(self, reactor, time):
method test_sync_loop_shutdown (line 121) | def test_sync_loop_shutdown(self, reactor):
method test_sync_process_save_log (line 129) | def test_sync_process_save_log(self, time):
method test_sync_process_flush_queues (line 155) | def test_sync_process_flush_queues(self, time):
method test_sync_publish (line 170) | def test_sync_publish(self, reactor):
method test_sync_publish_replace (line 180) | def test_sync_publish_replace(self, reactor):
method test_sync_publish_duplicate (line 191) | def test_sync_publish_duplicate(self, reactor):
method test_sync_subscribe (line 199) | def test_sync_subscribe(self):
method test_sync_unsubscribe (line 209) | def test_sync_unsubscribe(self):
method test_sync_notify (line 223) | def test_sync_notify(self, reactor):
FILE: tests/kubernetes_test.py
function mock_kubernetes_task (line 23) | def mock_kubernetes_task():
function mock_kubernetes_cluster (line 38) | def mock_kubernetes_cluster():
function mock_disabled_kubernetes_cluster (line 53) | def mock_disabled_kubernetes_cluster():
function mock_event_factory (line 64) | def mock_event_factory(
function test_get_event_logger_add_unique_handlers (line 83) | def test_get_event_logger_add_unique_handlers(mock_kubernetes_task):
function test_handle_event_log_event_info_exception (line 95) | def test_handle_event_log_event_info_exception(mock_kubernetes_task):
function test_handle_event_exit_early_on_misrouted_event (line 107) | def test_handle_event_exit_early_on_misrouted_event(mock_kubernetes_task):
function test_handle_event_running (line 123) | def test_handle_event_running(mock_kubernetes_task):
function test_handle_event_exit_on_finished (line 131) | def test_handle_event_exit_on_finished(mock_kubernetes_task):
function test_handle_event_exit_on_failed (line 175) | def test_handle_event_exit_on_failed(mock_kubernetes_task):
function test_handle_event_spot_interruption_exit (line 187) | def test_handle_event_spot_interruption_exit(mock_kubernetes_task):
function test_handle_event_node_scaledown_exit (line 255) | def test_handle_event_node_scaledown_exit(mock_kubernetes_task):
function test_handle_event_exit_not_terminated (line 300) | def test_handle_event_exit_not_terminated(mock_kubernetes_task):
function test_handle_event_abnormal_exit (line 338) | def test_handle_event_abnormal_exit(mock_kubernetes_task):
function test_handle_event_missing_state (line 383) | def test_handle_event_missing_state(mock_kubernetes_task):
function test_handle_event_code_from_state (line 416) | def test_handle_event_code_from_state(mock_kubernetes_task):
function test_handle_event_lost (line 461) | def test_handle_event_lost(mock_kubernetes_task):
function test_create_task_disabled (line 473) | def test_create_task_disabled():
function test_create_task (line 505) | def test_create_task(mock_kubernetes_cluster):
function test_create_task_with_task_id (line 536) | def test_create_task_with_task_id(mock_kubernetes_cluster):
function test_create_task_with_invalid_task_id (line 569) | def test_create_task_with_invalid_task_id(mock_kubernetes_cluster):
function test_create_task_with_config (line 603) | def test_create_task_with_config(mock_kubernetes_cluster):
function test_process_event_task (line 678) | def test_process_event_task(mock_kubernetes_cluster):
function test_process_event_task_invalid_id (line 689) | def test_process_event_task_invalid_id(mock_kubernetes_cluster):
function test_stop_default (line 700) | def test_stop_default(mock_kubernetes_cluster):
function test_stop_disabled (line 710) | def test_stop_disabled():
function test_set_enabled_enable_already_on (line 716) | def test_set_enabled_enable_already_on(mock_kubernetes_cluster):
function test_set_enabled_enable (line 732) | def test_set_enabled_enable(mock_disabled_kubernetes_cluster):
function test_set_enabled_disable (line 748) | def test_set_enabled_disable(mock_kubernetes_cluster):
function test_configure_default_volumes (line 760) | def test_configure_default_volumes():
function test_submit_disabled (line 782) | def test_submit_disabled(mock_disabled_kubernetes_cluster, mock_kubernet...
function test_submit (line 790) | def test_submit(mock_kubernetes_cluster, mock_kubernetes_task):
function test_recover (line 798) | def test_recover(mock_kubernetes_cluster, mock_kubernetes_task):
function test_kuberntes_cluster_repository (line 807) | def test_kuberntes_cluster_repository():
FILE: tests/mcp_reconfigure_test.py
class TestMCPReconfigure (line 21) | class TestMCPReconfigure(TestCase):
method _get_config (line 170) | def _get_config(self, idx, output_dir):
method _get_runs_to_schedule (line 175) | def _get_runs_to_schedule(self, sched):
method setup_mcp (line 181) | def setup_mcp(self):
method teardown_mcp (line 189) | def teardown_mcp(self):
method reconfigure (line 193) | def reconfigure(self):
method test_job_list (line 199) | def test_job_list(self):
method test_job_unchanged (line 209) | def test_job_unchanged(self):
method test_job_unchanged_disabled (line 235) | def test_job_unchanged_disabled(self):
method test_job_removed (line 247) | def test_job_removed(self):
method test_job_changed (line 265) | def test_job_changed(self):
method test_job_changed_disabled (line 293) | def test_job_changed_disabled(self):
method test_job_new (line 303) | def test_job_new(self):
method test_daily_reschedule (line 319) | def test_daily_reschedule(self):
method test_action_added (line 339) | def test_action_added(self):
FILE: tests/mcp_test.py
class TestMasterControlProgram (line 21) | class TestMasterControlProgram:
method setup_mcp (line 26) | def setup_mcp(self):
method test_reconfigure_default (line 38) | def test_reconfigure_default(self):
method test_reconfigure_namespace (line 44) | def test_reconfigure_namespace(self):
method test_load_config (line 58) | def test_load_config(self, reconfigure, namespace):
method test_apply_config (line 81) | def test_apply_config(self, mock_repo, mock_cluster_repo, mock_k8s_clu...
method test_update_state_watcher_config_changed (line 117) | def test_update_state_watcher_config_changed(self):
method test_update_state_watcher_config_no_change (line 134) | def test_update_state_watcher_config_no_change(self):
class TestMasterControlProgramRestoreState (line 142) | class TestMasterControlProgramRestoreState(TestCase):
method setup_mcp (line 144) | def setup_mcp(self):
method teardown_mcp (line 155) | def teardown_mcp(self):
method test_restore_state (line 159) | def test_restore_state(self):
FILE: tests/mesos_test.py
class TestMesosClusterRepository (line 14) | class TestMesosClusterRepository(TestCase):
method mock_cluster (line 16) | def mock_cluster(self):
method test_get_cluster_repeated_mesos_address (line 28) | def test_get_cluster_repeated_mesos_address(self):
method test_shutdown (line 34) | def test_shutdown(self):
method test_configure (line 41) | def test_configure(self):
function mock_task_event (line 86) | def mock_task_event(
class TestMesosTask (line 105) | class TestMesosTask(TestCase):
method setup (line 107) | def setup(self):
method test_aws_credentials_redacted (line 135) | def test_aws_credentials_redacted(self):
method test_handle_staging (line 141) | def test_handle_staging(self):
method test_handle_starting (line 149) | def test_handle_starting(self):
method test_handle_running (line 157) | def test_handle_running(self):
method test_handle_running_for_other_task (line 165) | def test_handle_running_for_other_task(self):
method test_handle_finished (line 173) | def test_handle_finished(self):
method test_handle_failed (line 184) | def test_handle_failed(self):
method test_handle_killed (line 196) | def test_handle_killed(self):
method test_handle_lost (line 208) | def test_handle_lost(self):
method test_handle_error (line 220) | def test_handle_error(self):
method test_handle_terminal_event_offer_timeout (line 232) | def test_handle_terminal_event_offer_timeout(self):
method test_handle_success_sequence (line 246) | def test_handle_success_sequence(self):
method test_log_event_error (line 275) | def test_log_event_error(self):
method test_get_event_logger_add_unique_handlers (line 291) | def test_get_event_logger_add_unique_handlers(self):
class TestMesosCluster (line 303) | class TestMesosCluster(TestCase):
method setup_mocks (line 305) | def setup_mocks(self):
method test_init (line 324) | def test_init(self, mock_socket):
method test_init_disabled (line 377) | def test_init_disabled(self):
method test_set_enabled_off (line 385) | def test_set_enabled_off(self):
method test_set_enabled_on (line 395) | def test_set_enabled_on(self):
method test_set_enabled_on_already (line 416) | def test_set_enabled_on_already(self):
method test_configure_tasks (line 423) | def test_configure_tasks(self):
method test_submit (line 450) | def test_submit(self):
method test_submit_with_clusterman (line 469) | def test_submit_with_clusterman(self):
method test_submit_disabled (line 501) | def test_submit_disabled(self):
method test_recover (line 515) | def test_recover(self):
method test_recover_disabled (line 528) | def test_recover_disabled(self):
method test_create_task_defaults (line 538) | def test_create_task_defaults(self, mock_task):
method test_create_task_with_task_id (line 576) | def test_create_task_with_task_id(self, mock_task):
method test_create_task_disabled (line 605) | def test_create_task_disabled(self, mock_task):
method test_create_task_with_configuration (line 625) | def test_create_task_with_configuration(self, mock_task):
method test_process_event_task (line 696) | def test_process_event_task(self):
method test_process_event_task_id_invalid (line 706) | def test_process_event_task_id_invalid(self):
method test_process_event_control_stop (line 716) | def test_process_event_control_stop(self):
method test_stop_default (line 726) | def test_stop_default(self):
method test_stop_disabled (line 737) | def test_stop_disabled(self):
method test_kill (line 742) | def test_kill(self):
FILE: tests/metrics_test.py
function all_metrics (line 9) | def all_metrics():
function test_get_metric (line 14) | def test_get_metric(all_metrics):
function test_timer (line 40) | def test_timer(mock_get_metric):
function test_count (line 56) | def test_count(mock_get_metric):
function test_meter (line 72) | def test_meter(mock_get_metric):
function test_gauge (line 88) | def test_gauge(mock_get_metric):
function test_histogram (line 104) | def test_histogram(mock_get_metric):
function test_view_all_metrics_empty (line 119) | def test_view_all_metrics_empty():
function test_view_all_metrics (line 130) | def test_view_all_metrics():
FILE: tests/mocks.py
class MockAction (line 9) | class MockAction(MagicMock):
method __init__ (line 10) | def __init__(self, *args, **kwargs):
class MockActionGraph (line 17) | class MockActionGraph(MagicMock):
method __init__ (line 18) | def __init__(self, *args, **kwargs):
method __getitem__ (line 24) | def __getitem__(self, item):
method get_required_actions (line 29) | def get_required_actions(self, name):
class MockActionRun (line 33) | class MockActionRun(MagicMock):
method __init__ (line 34) | def __init__(self, *args, **kwargs):
class MockActionRunCollection (line 42) | class MockActionRunCollection(MagicMock):
method __init__ (line 43) | def __init__(self, *args, **kwargs):
method __getitem__ (line 48) | def __getitem__(self, item):
class MockJobRun (line 54) | class MockJobRun(MagicMock):
method __init__ (line 55) | def __init__(self, *args, **kwargs):
class MockNode (line 66) | class MockNode(MagicMock):
method __init__ (line 67) | def __init__(self, hostname=None):
method run (line 71) | def run(self, runnable):
class MockNodePool (line 76) | class MockNodePool:
method __init__ (line 79) | def __init__(self, *node_names):
method __getitem__ (line 88) | def __getitem__(self, value):
method next (line 95) | def next(self):
class MockJobRunCollection (line 107) | class MockJobRunCollection(MagicMock):
method __iter__ (line 108) | def __iter__(self):
FILE: tests/node_test.py
function create_mock_node (line 22) | def create_mock_node(name=None):
function create_mock_pool (line 29) | def create_mock_pool():
class TestNodePoolRepository (line 33) | class TestNodePoolRepository(TestCase):
method setup_store (line 35) | def setup_store(self):
method teardown_store (line 41) | def teardown_store(self):
method test_single_instance (line 44) | def test_single_instance(self):
method test_get_by_name (line 48) | def test_get_by_name(self):
method test_get_by_name_miss (line 52) | def test_get_by_name_miss(self):
method test_clear (line 55) | def test_clear(self):
method test_update_from_config (line 60) | def test_update_from_config(self):
method test_nodes_by_name (line 81) | def test_nodes_by_name(self):
method test_get_node (line 87) | def test_get_node(self):
class TestKnownHost (line 92) | class TestKnownHost(TestCase):
method setup_known_hosts (line 94) | def setup_known_hosts(self):
method test_get_public_key (line 99) | def test_get_public_key(self):
method test_get_public_key_not_found (line 105) | def test_get_public_key_not_found(self):
class TestDetermineJitter (line 110) | class TestDetermineJitter(TestCase):
method setup_node_settings (line 112) | def setup_node_settings(self):
method patch_random (line 120) | def patch_random(self):
method test_jitter_under_min_load (line 125) | def test_jitter_under_min_load(self):
method test_jitter_with_load_factor (line 129) | def test_jitter_with_load_factor(self):
method test_jitter_with_max_delay (line 134) | def test_jitter_with_max_delay(self):
function build_node (line 140) | def build_node(
class TestNode (line 152) | class TestNode(TestCase):
class TestConnection (line 153) | class TestConnection:
method openChannel (line 154) | def openChannel(self, chan):
method setup_node (line 158) | def setup_node(self):
method test_output_logging (line 161) | def test_output_logging(self):
method test_from_config (line 176) | def test_from_config(self):
method test__eq__true (line 198) | def test__eq__true(self):
method test__eq__false_config_changed (line 205) | def test__eq__false_config_changed(self):
method test__eq__false_pub_key_changed (line 209) | def test__eq__false_pub_key_changed(self):
method test__eq__false_ssh_options_changed (line 213) | def test__eq__false_ssh_options_changed(self):
method test_stop_not_tracked (line 218) | def test_stop_not_tracked(self):
method test_stop (line 225) | def test_stop(self):
class TestNodePool (line 236) | class TestNodePool(TestCase):
method setup_nodes (line 238) | def setup_nodes(self):
method test_from_config (line 242) | def test_from_config(self):
method test__init__ (line 250) | def test__init__(self):
method test__eq__ (line 254) | def test__eq__(self):
method test_next (line 258) | def test_next(self):
method test_next_round_robin (line 263) | def test_next_round_robin(self):
FILE: tests/sandbox.py
function wait_on_sandbox (line 31) | def wait_on_sandbox(func, delay=0.1, max_wait=5.0):
function wait_on_state (line 43) | def wait_on_state(client_func, url, state, field="state"):
function wait_on_proc_terminate (line 53) | def wait_on_proc_terminate(pid):
function build_waiter_func (line 64) | def build_waiter_func(client_func, url):
function handle_output (line 68) | def handle_output(cmd, out_err, returncode):
function find_unused_port (line 82) | def find_unused_port():
class TronSandboxException (line 91) | class TronSandboxException(Exception):
class SandboxTestCase (line 95) | class SandboxTestCase(TestCase):
method make_sandbox (line 102) | def make_sandbox(self):
method delete_sandbox (line 108) | def delete_sandbox(self):
method start_with_config (line 113) | def start_with_config(self, config):
method restart_trond (line 117) | def restart_trond(self):
class ClientProxy (line 126) | class ClientProxy:
method __init__ (line 131) | def __init__(self, client, log_filename):
method log_contents (line 135) | def log_contents(self):
method wrap (line 140) | def wrap(self, func, *args, **kwargs):
method __getattr__ (line 151) | def __getattr__(self, name):
function verify_environment (line 159) | def verify_environment():
class TronSandbox (line 167) | class TronSandbox:
method __init__ (line 170) | def __init__(self):
method abs_path (line 187) | def abs_path(self, filename):
method setup_logging_conf (line 191) | def setup_logging_conf(self):
method delete (line 199) | def delete(self):
method save_config (line 204) | def save_config(self, config_text):
method run_command (line 208) | def run_command(self, command_name, args=None, stdin_lines=None):
method tronctl (line 222) | def tronctl(self, *args):
method tronview (line 226) | def tronview(self, *args):
method trond (line 231) | def trond(self, *args):
method tronfig (line 245) | def tronfig(
method get_trond_pid (line 254) | def get_trond_pid(self):
method shutdown_trond (line 260) | def shutdown_trond(self, sig_num=signal.SIGTERM):
FILE: tests/scheduler_test.py
class TestSchedulerFromConfig (line 24) | class TestSchedulerFromConfig(TestCase):
method test_cron_scheduler (line 25) | def test_cron_scheduler(self):
method test_daily_scheduler (line 35) | def test_daily_scheduler(self):
class GeneralSchedulerTestCase (line 51) | class GeneralSchedulerTestCase(testingutils.MockTimeTestCase):
method expected_time (line 55) | def expected_time(self, date):
method build_scheduler (line 59) | def build_scheduler(self):
method test_next_run_time (line 66) | def test_next_run_time(self):
method test_next_run_time_with_jitter (line 74) | def test_next_run_time_with_jitter(self, mock_jitter):
method test__str__ (line 81) | def test__str__(self):
method test__str__with_jitter (line 84) | def test__str__with_jitter(self):
class GeneralSchedulerTimeTestBase (line 89) | class GeneralSchedulerTimeTestBase(testingutils.MockTimeTestCase):
method build_scheduler (line 94) | def build_scheduler(self):
class GeneralSchedulerTodayTest (line 98) | class GeneralSchedulerTodayTest(GeneralSchedulerTimeTestBase):
method test (line 102) | def test(self):
class GeneralSchedulerTomorrowTest (line 117) | class GeneralSchedulerTomorrowTest(GeneralSchedulerTimeTestBase):
method test (line 121) | def test(self):
class GeneralSchedulerLongJobRunTest (line 137) | class GeneralSchedulerLongJobRunTest(GeneralSchedulerTimeTestBase):
method test_long_jobs_dont_wedge_scheduler (line 141) | def test_long_jobs_dont_wedge_scheduler(self):
class GeneralSchedulerDSTTest (line 155) | class GeneralSchedulerDSTTest(testingutils.MockTimeTestCase):
method hours_until_time (line 160) | def hours_until_time(self, run_time, sch):
method hours_diff_at_datetime (line 167) | def hours_diff_at_datetime(self, sch, *args, **kwargs):
method _assert_range (line 178) | def _assert_range(self, x, lower, upper):
method test_fall_back (line 182) | def test_fall_back(self):
method test_correct_time (line 205) | def test_correct_time(self):
method test_spring_forward (line 210) | def test_spring_forward(self):
method test_handles_tz_specific_jobs_with_tz_specific_start_time (line 233) | def test_handles_tz_specific_jobs_with_tz_specific_start_time(self):
method test_handles_unsetting_the_time_zone (line 238) | def test_handles_unsetting_the_time_zone(self):
method test_handles_changing_the_time_zone (line 243) | def test_handles_changing_the_time_zone(self):
function parse_groc (line 251) | def parse_groc(config):
function scheduler_from_config (line 256) | def scheduler_from_config(config):
class ComplexParserTest (line 260) | class ComplexParserTest(testingutils.MockTimeTestCase):
method test_parse_all (line 264) | def test_parse_all(self):
method test_parse_no_weekday (line 277) | def test_parse_no_weekday(self):
method test_parse_no_month (line 287) | def test_parse_no_month(self):
method test_parse_monthly (line 295) | def test_parse_monthly(self):
method test_wildcards (line 304) | def test_wildcards(self):
method test_daily (line 312) | def test_daily(self):
method test_daily_with_time (line 321) | def test_daily_with_time(self):
method test_weekly (line 332) | def test_weekly(self):
method test_weekly_in_month (line 346) | def test_weekly_in_month(self):
method test_monthly (line 364) | def test_monthly(self):
FILE: tests/serialize/filehandler_test.py
class TestFileHandleWrapper (line 23) | class TestFileHandleWrapper(TestCase):
method setup_fh_wrapper (line 25) | def setup_fh_wrapper(self):
method teardown_fh_wrapper (line 31) | def teardown_fh_wrapper(self):
method test_init (line 35) | def test_init(self):
method test_close (line 38) | def test_close(self):
method test_close_with_write (line 44) | def test_close_with_write(self):
method test_write (line 53) | def test_write(self):
method test_close_many (line 72) | def test_close_many(self):
method test_context_manager (line 77) | def test_context_manager(self):
class TestFileHandleManager (line 85) | class TestFileHandleManager(TestCase):
method setup_fh_manager (line 87) | def setup_fh_manager(self):
method teardown_fh_manager (line 95) | def teardown_fh_manager(self):
method test_get_instance (line 98) | def test_get_instance(self):
method test_set_max_idle_time (line 103) | def test_set_max_idle_time(self):
method test_open (line 108) | def test_open(self):
method test_cleanup_none (line 122) | def test_cleanup_none(self):
method test_cleanup_single (line 128) | def test_cleanup_single(self):
method test_cleanup_many (line 139) | def test_cleanup_many(self):
method test_cleanup_opened (line 162) | def test_cleanup_opened(self):
method test_cleanup_natural (line 175) | def test_cleanup_natural(self):
method test_remove (line 192) | def test_remove(self):
method test_update (line 203) | def test_update(self):
class TestOutputStreamSerializer (line 218) | class TestOutputStreamSerializer(TestCase):
method setup_serializer (line 220) | def setup_serializer(self):
method teardown_test_dir (line 228) | def teardown_test_dir(self):
method _write_contents (line 231) | def _write_contents(self):
method test_open (line 235) | def test_open(self):
method test_init_with_output_path (line 243) | def test_init_with_output_path(self):
method test_tail (line 248) | def test_tail(self):
method test_tail_num_lines (line 252) | def test_tail_num_lines(self):
method test_tail_file_does_not_exist (line 256) | def test_tail_file_does_not_exist(self):
class TestOutputPath (line 261) | class TestOutputPath(TestCase):
method setup_path (line 263) | def setup_path(self):
method test__init__ (line 266) | def test__init__(self):
method test__iter__ (line 274) | def test__iter__(self):
method test__str__ (line 277) | def test__str__(self):
method test_append (line 281) | def test_append(self):
method test_clone (line 285) | def test_clone(self):
method test_clone_with_parts (line 295) | def test_clone_with_parts(self):
method test_delete (line 299) | def test_delete(self):
method test__eq__ (line 305) | def test__eq__(self):
method test__ne__ (line 309) | def test__ne__(self):
FILE: tests/serialize/runstate/dynamodb_state_store_test.py
function mock_transact_write_items (line 15) | def mock_transact_write_items(self):
function store (line 62) | def store():
function small_job (line 104) | def small_job():
function small_object (line 112) | def small_object():
function large_object (line 126) | def large_object():
class TestDynamoDBStateStore (line 147) | class TestDynamoDBStateStore:
method test_save (line 148) | def test_save(self, store, small_job, small_object):
method test_save_multi_partition_object (line 186) | def test_save_multi_partition_object(self, store, large_object):
method test_restore (line 206) | def test_restore(self, store, small_object):
method test_restore_multi_partition_object (line 221) | def test_restore_multi_partition_object(self, store, large_object):
method test_delete_item (line 242) | def test_delete_item(self, store, small_object):
method test_delete_multi_partition_item (line 257) | def test_delete_multi_partition_item(self, store, large_object):
method test_delete_if_val_is_none (line 277) | def test_delete_if_val_is_none(self, store, small_object):
method test_retry_saving (line 323) | def test_retry_saving(
method test_calculate_backoff_delay (line 360) | def test_calculate_backoff_delay(self, store, attempt, expected_delay):
method test_retry_reading (line 364) | def test_retry_reading(self, store):
method test_restore_exception_propagation (line 387) | def test_restore_exception_propagation(self, store):
method test_serialization_failure_preserves_existing_row (line 401) | def test_serialization_failure_preserves_existing_row(self, store, sma...
method test_serialization_retry_succeeds (line 429) | def test_serialization_retry_succeeds(self, store, small_object):
method test_delete_sentinel_proceeds_with_deletion (line 452) | def test_delete_sentinel_proceeds_with_deletion(self, store, small_obj...
FILE: tests/serialize/runstate/shelvestore_test.py
class TestShelveStateStore (line 15) | class TestShelveStateStore(TestCase):
method setup_store (line 17) | def setup_store(self):
method teardown_store (line 23) | def teardown_store(self):
method test__init__ (line 26) | def test__init__(self):
method test_save (line 29) | def test_save(self):
method test_delete (line 52) | def test_delete(self):
method test_restore (line 81) | def test_restore(self):
FILE: tests/serialize/runstate/statemanager_test.py
class TestPersistenceManagerFactory (line 25) | class TestPersistenceManagerFactory(TestCase):
method test_from_config_shelve (line 26) | def test_from_config_shelve(self):
class TestStateSaveBuffer (line 43) | class TestStateSaveBuffer(TestCase):
method setup_buffer (line 45) | def setup_buffer(self):
method test_save (line 49) | def test_save(self):
method test__iter__ (line 58) | def test__iter__(self):
class TestPersistentStateManager (line 66) | class TestPersistentStateManager(TestCase):
method setup_manager (line 68) | def setup_manager(self):
method test__init__ (line 74) | def test__init__(self):
method test_keys_for_items (line 77) | def test_keys_for_items(self):
method test_restore (line 84) | def test_restore(self):
method test_restore_runs_for_job (line 111) | def test_restore_runs_for_job(self):
method test_restore_runs_for_job_one_missing (line 126) | def test_restore_runs_for_job_one_missing(self):
method test_restore_dicts (line 141) | def test_restore_dicts(self):
method test_save (line 164) | def test_save(self):
method test_save_failed (line 170) | def test_save_failed(self):
method test_save_while_disabled (line 180) | def test_save_while_disabled(self):
method test_delete (line 185) | def test_delete(self):
method test_cleanup (line 191) | def test_cleanup(self):
method test_disabled (line 195) | def test_disabled(self):
method test_disabled_with_exception (line 200) | def test_disabled_with_exception(self):
method test_disabled_nested (line 208) | def test_disabled_nested(self):
class TestStateChangeWatcher (line 215) | class TestStateChangeWatcher(TestCase):
method setup_watcher (line 217) | def setup_watcher(self):
method test_update_from_config_no_change (line 222) | def test_update_from_config_no_change(self):
method test_update_from_config_changed (line 233) | def test_update_from_config_changed(self, mock_factory):
method test_save_job (line 245) | def test_save_job(self):
method test_shutdown (line 254) | def test_shutdown(self):
method test_disabled (line 259) | def test_disabled(self):
method test_restore (line 263) | def test_restore(self):
method test_handler_mesos_change (line 268) | def test_handler_mesos_change(self):
method test_handler_job_state_change (line 279) | def test_handler_job_state_change(self):
method test_handler_job_new_run (line 288) | def test_handler_job_new_run(self):
method test_handler_job_run_state_change (line 312) | def test_handler_job_run_state_change(self):
method test_handler_job_run_removed (line 324) | def test_handler_job_run_removed(self):
FILE: tests/serialize/runstate/yamlstore_test.py
class TestYamlStateStore (line 13) | class TestYamlStateStore(TestCase):
method setup_store (line 15) | def setup_store(self):
method teardown_store (line 31) | def teardown_store(self):
method test_restore (line 37) | def test_restore(self):
method test_restore_missing_type_key (line 48) | def test_restore_missing_type_key(self):
method test_restore_file_missing (line 57) | def test_restore_file_missing(self):
method test_save (line 61) | def test_save(self):
method test_delete (line 82) | def test_delete(self):
FILE: tests/ssh_test.py
class TestClientTransport (line 13) | class TestClientTransport(TestCase):
method setup_transport (line 15) | def setup_transport(self):
method test_verifyHostKey_missing_pub_key (line 25) | def test_verifyHostKey_missing_pub_key(self):
method test_verifyHostKey_matching_pub_key (line 31) | def test_verifyHostKey_matching_pub_key(self, mock_keys):
method test_verifyHostKey_mismatch_pub_key (line 39) | def test_verifyHostKey_mismatch_pub_key(self, _):
method test_connnectionSecure (line 44) | def test_connnectionSecure(self):
class TestSSHAuthOptions (line 54) | class TestSSHAuthOptions(TestCase):
method test_from_config_none (line 55) | def test_from_config_none(self):
method test_from_config_both (line 61) | def test_from_config_both(self):
method test__eq__true (line 68) | def test__eq__true(self):
method test__eq__false (line 75) | def test__eq__false(self):
FILE: tests/testingutils.py
class MockReactorTestCase (line 18) | class MockReactorTestCase(TestCase):
method class_setup_patched_reactor (line 25) | def class_setup_patched_reactor(self):
method teardown_patched_reactor (line 31) | def teardown_patched_reactor(self):
method setup_mock_reactor (line 35) | def setup_mock_reactor(self):
class MockTimeTestCase (line 41) | class MockTimeTestCase(TestCase):
method setup_current_time (line 46) | def setup_current_time(self):
method teardown_current_time (line 52) | def teardown_current_time(self):
function retry (line 59) | def retry(max_tries=3, delay=0.1, exceptions=(KeyError, IndexError)):
function autospec_method (line 79) | def autospec_method(method, *args, **kwargs):
FILE: tests/tools/sync_tron_state_from_k8s_test.py
function create_mock_pod (line 13) | def create_mock_pod(name: str, phase: str, labels: dict[str, str], creat...
class TestSyncTronStateFromK8s (line 19) | class TestSyncTronStateFromK8s:
method setup_test_data (line 21) | def setup_test_data(self):
method test_get_matching_pod (line 118) | def test_get_matching_pod(self, job_name, run_num, expected_pod_name):
method test_get_tron_state_from_api (line 127) | def test_get_tron_state_from_api(self, mock_client, mock_get_client_co...
method test_update_tron (line 142) | def test_update_tron(self, mock_subprocess_run):
FILE: tests/trond_test.py
class TrondEndToEndTestCase (line 63) | class TrondEndToEndTestCase(sandbox.SandboxTestCase):
method test_end_to_end_basic (line 64) | def test_end_to_end_basic(self):
method test_node_reconfig (line 124) | def test_node_reconfig(self):
class TronCommandsTestCase (line 175) | class TronCommandsTestCase(sandbox.SandboxTestCase):
method test_tronview (line 176) | def test_tronview(self):
method test_tronctl_with_job (line 189) | def test_tronctl_with_job(self):
method test_tronfig (line 218) | def test_tronfig(self):
method test_tronfig_failure (line 223) | def test_tronfig_failure(self):
class JobEndToEndTestCase (line 235) | class JobEndToEndTestCase(sandbox.SandboxTestCase):
method test_cleanup_on_failure (line 236) | def test_cleanup_on_failure(self):
method test_skip_failed_actions (line 272) | def test_skip_failed_actions(self):
method test_failure_on_multi_step_job_doesnt_wedge_tron (line 312) | def test_failure_on_multi_step_job_doesnt_wedge_tron(self):
method test_cancel_schedules_a_new_run (line 340) | def test_cancel_schedules_a_new_run(self):
method test_job_queueing_false_with_overlap (line 370) | def test_job_queueing_false_with_overlap(self):
method test_trond_restart_job_with_run_history (line 409) | def test_trond_restart_job_with_run_history(self):
method test_trond_restart_job_running_with_dependencies (line 444) | def test_trond_restart_job_running_with_dependencies(self):
FILE: tests/trondaemon_test.py
class TronDaemonTestCase (line 12) | class TronDaemonTestCase(TestCase):
method setup (line 16) | def setup(self):
method teardown (line 24) | def teardown(self):
method test_init (line 29) | def test_init(self):
method test_run_uses_context (line 40) | def test_run_uses_context(self):
method test_run_manhole_new_manhole (line 56) | def test_run_manhole_new_manhole(self):
FILE: tests/utils/collections_test.py
class TestMappingCollections (line 14) | class TestMappingCollections(TestCase):
method setup_collection (line 16) | def setup_collection(self):
method test_filter_by_name (line 20) | def test_filter_by_name(self):
method test_remove_missing (line 27) | def test_remove_missing(self):
method test_remove (line 30) | def test_remove(self):
method test_contains_item_false (line 37) | def test_contains_item_false(self):
method test_contains_item_not_equal (line 42) | def test_contains_item_not_equal(self):
method test_contains_item_true (line 49) | def test_contains_item_true(self):
method test_add_contains (line 54) | def test_add_contains(self):
method test_add_new (line 60) | def test_add_new(self):
method test_replace (line 66) | def test_replace(self):
FILE: tests/utils/crontab_test.py
class TestConvertPredefined (line 11) | class TestConvertPredefined(TestCase):
method test_convert_predefined_valid (line 12) | def test_convert_predefined_valid(self):
method test_convert_predefined_invalid (line 16) | def test_convert_predefined_invalid(self):
method test_convert_predefined_none (line 19) | def test_convert_predefined_none(self):
class TestParseCrontab (line 24) | class TestParseCrontab(TestCase):
method test_parse_asterisk (line 25) | def test_parse_asterisk(self):
method test_parse (line 37) | def test_parse(self, mock_dow, mock_month, mock_monthday, mock_hour, m...
method test_full_crontab_line (line 46) | def test_full_crontab_line(self):
method test_full_crontab_line_with_last (line 58) | def test_full_crontab_line_with_last(self):
class TestMinuteFieldParser (line 71) | class TestMinuteFieldParser(TestCase):
method setup_parser (line 73) | def setup_parser(self):
method test_validate_bounds (line 76) | def test_validate_bounds(self):
method test_get_values_asterisk (line 81) | def test_get_values_asterisk(self):
method test_get_values_min_only (line 84) | def test_get_values_min_only(self):
method test_get_values_with_step (line 88) | def test_get_values_with_step(self):
method test_get_values_with_step_and_range (line 91) | def test_get_values_with_step_and_range(self):
method test_get_values_with_step_and_overflow_range (line 94) | def test_get_values_with_step_and_overflow_range(self):
method test_parse_with_groups (line 97) | def test_parse_with_groups(self):
method test_parse_with_groups_and_ranges (line 100) | def test_parse_with_groups_and_ranges(self):
class TestMonthFieldParser (line 105) | class TestMonthFieldParser(TestCase):
method setup_parser (line 107) | def setup_parser(self):
method test_parse (line 110) | def test_parse(self):
class TestWeekdayFieldParser (line 115) | class TestWeekdayFieldParser(TestCase):
method setup_parser (line 117) | def setup_parser(self):
method test_parser (line 120) | def test_parser(self):
class TestMonthdayFieldParser (line 125) | class TestMonthdayFieldParser(TestCase):
method setup_parser (line 127) | def setup_parser(self):
method test_parse_last (line 130) | def test_parse_last(self):
class TestComplexExpressions (line 135) | class TestComplexExpressions(TestCase):
method setup_parser (line 137) | def setup_parser(self):
method test_complex_expression (line 140) | def test_complex_expression(self):
class TestInvalidInputs (line 145) | class TestInvalidInputs(TestCase):
method setup_parser (line 147) | def setup_parser(self):
method test_invalid_expression (line 150) | def test_invalid_expression(self):
class TestBoundaryValues (line 155) | class TestBoundaryValues(TestCase):
method setup_parser (line 157) | def setup_parser(self):
method test_boundary_values (line 160) | def test_boundary_values(self):
FILE: tests/utils/logreader_test.py
function static_conf_patch (line 18) | def static_conf_patch(args):
function test_read_log_stream_for_action_run_not_available (line 22) | def test_read_log_stream_for_action_run_not_available():
function test_read_log_stream_for_action_run (line 34) | def test_read_log_stream_for_action_run():
function test_read_log_stream_for_action_run_tz (line 101) | def test_read_log_stream_for_action_run_tz(local_datetime, expected_date...
function test_read_log_stream_for_action_run_for_long_output (line 127) | def test_read_log_stream_for_action_run_for_long_output():
function test_decompose_action_id_file_not_found (line 163) | def test_decompose_action_id_file_not_found():
function test_decompose_action_id_yaml_error (line 174) | def test_decompose_action_id_yaml_error():
function test_decompose_action_id_generic_error (line 187) | def test_decompose_action_id_generic_error():
function test_decompose_action_id_service_not_found (line 200) | def test_decompose_action_id_service_not_found():
FILE: tests/utils/observer_test.py
class TestObservable (line 12) | class TestObservable(TestCase):
method setup_observer (line 14) | def setup_observer(self):
method test_attach (line 17) | def test_attach(self):
method test_listen_seq (line 25) | def test_listen_seq(self):
method test_notify (line 34) | def test_notify(self):
class TestObserverClear (line 43) | class TestObserverClear(TestCase):
method setup_observer (line 45) | def setup_observer(self):
method test_clear_listeners_all (line 56) | def test_clear_listeners_all(self):
method test_clear_listeners_some (line 60) | def test_clear_listeners_some(self):
method test_remove_observer_none (line 65) | def test_remove_observer_none(self):
method test_remove_observer (line 75) | def test_remove_observer(self):
class MockObserver (line 88) | class MockObserver(Observer):
method __init__ (line 89) | def __init__(self, obs, event):
method handler (line 96) | def handler(self, obs, event, event_data):
class TestObserver (line 103) | class TestObserver(TestCase):
method setup_observer (line 105) | def setup_observer(self):
method test_watch (line 108) | def test_watch(self):
FILE: tests/utils/proxy_test.py
class DummyTarget (line 11) | class DummyTarget:
method __init__ (line 12) | def __init__(self, v):
method foo (line 15) | def foo(self):
method not_foo (line 19) | def not_foo(self):
method equals (line 22) | def equals(self, b, sometimes=False):
class DummyObject (line 28) | class DummyObject:
method __init__ (line 29) | def __init__(self, proxy):
method __getattr__ (line 32) | def __getattr__(self, item):
class TestCollectionProxy (line 36) | class TestCollectionProxy(TestCase):
method setup_proxy (line 38) | def setup_proxy(self):
method test_add (line 50) | def test_add(self):
method test_perform (line 54) | def test_perform(self):
method test_perform_not_defined (line 58) | def test_perform_not_defined(self):
method test_perform_with_params (line 61) | def test_perform_with_params(self):
class TestAttributeProxy (line 70) | class TestAttributeProxy(TestCase):
method setup_proxy (line 72) | def setup_proxy(self):
method test_add (line 77) | def test_add(self):
method test_perform (line 81) | def test_perform(self):
method test_perform_not_defined (line 85) | def test_perform_not_defined(self):
FILE: tests/utils/state_test.py
class TestStateMachineSimple (line 7) | class TestStateMachineSimple(TestCase):
method build_machine (line 9) | def build_machine(self):
method test_transition_many (line 15) | def test_transition_many(self):
method test_check (line 28) | def test_check(self):
class TestStateMachineMultiOption (line 34) | class TestStateMachineMultiOption(TestCase):
method build_machine (line 36) | def build_machine(self):
method test_transition_many (line 47) | def test_transition_many(self):
method test_transition_set (line 63) | def test_transition_set(self):
FILE: tests/utils/timeutils_test.py
class TestTimeDelta (line 15) | class TestTimeDelta(TestCase):
method make_dates (line 17) | def make_dates(self):
method check_delta (line 25) | def check_delta(self, start, target, years=0, months=0, days=0):
method test_days (line 37) | def test_days(self):
method test_months (line 69) | def test_months(self):
method test_years (line 101) | def test_years(self):
method test_start_date_with_timezone (line 133) | def test_start_date_with_timezone(self):
class TestDuration (line 148) | class TestDuration(TestCase):
method setup_times (line 150) | def setup_times(self):
method test_duration (line 154) | def test_duration(self):
method test_duration_no_end (line 160) | def test_duration_no_end(self):
method test_duration_no_start (line 164) | def test_duration_no_start(self):
class TestDeltaTotalSeconds (line 168) | class TestDeltaTotalSeconds(TestCase):
method test (line 169) | def test(self):
class DateArithmeticTestCase (line 176) | class DateArithmeticTestCase(testingutils.MockTimeTestCase):
method _cmp_date (line 182) | def _cmp_date(self, item, dt):
method _cmp_day (line 185) | def _cmp_day(self, item, dt):
method _cmp_month (line 188) | def _cmp_month(self, item, dt):
method _cmp_year (line 191) | def _cmp_year(self, item, dt):
method test_shortdate (line 194) | def test_shortdate(self):
method test_shortdate_plus (line 197) | def test_shortdate_plus(self):
method test_shortdate_minus (line 202) | def test_shortdate_minus(self):
method test_day (line 207) | def test_day(self):
method test_day_minus (line 210) | def test_day_minus(self):
method test_day_plus (line 215) | def test_day_plus(self):
method test_month (line 220) | def test_month(self):
method test_month_plus (line 223) | def test_month_plus(self):
method test_month_minus (line 228) | def test_month_minus(self):
method test_year (line 233) | def test_year(self):
method test_year_plus (line 236) | def test_year_plus(self):
method test_year_minus (line 241) | def test_year_minus(self):
method test_unixtime (line 246) | def test_unixtime(self):
method test_unixtime_plus (line 250) | def test_unixtime_plus(self):
method test_unixtime_minus (line 254) | def test_unixtime_minus(self):
method test_daynumber (line 258) | def test_daynumber(self):
method test_daynumber_plus (line 262) | def test_daynumber_plus(self):
method test_daynumber_minus (line 266) | def test_daynumber_minus(self):
method test_hour (line 270) | def test_hour(self):
method test_hour_plus (line 274) | def test_hour_plus(self):
method test_hour_minus (line 278) | def test_hour_minus(self):
method test_bad_date_format (line 282) | def test_bad_date_format(self):
method test_round_day (line 285) | def test_round_day(self):
class DateArithmeticYMDHTest (line 291) | class DateArithmeticYMDHTest(TestCase):
method test_ym_plus (line 292) | def test_ym_plus(self):
method test_ym_minus (line 299) | def test_ym_minus(self):
method test_ymd_plus (line 306) | def test_ymd_plus(self):
method test_ymd_minus (line 313) | def test_ymd_minus(self):
method test_ymdh_plus (line 320) | def test_ymdh_plus(self):
method test_ymdh_minus (line 327) | def test_ymdh_minus(self):
method test_ymdhm_plus (line 334) | def test_ymdhm_plus(self):
method test_ymdhm_minus (line 341) | def test_ymdhm_minus(self):
method test_ym_minus_round (line 348) | def test_ym_minus_round(self):
method test_ymd_plus_whitespace (line 353) | def test_ymd_plus_whitespace(self):
method test_ymd_minus_whitespace (line 360) | def test_ymd_minus_whitespace(self):
class TestDateArithmeticWithTimezone (line 368) | class TestDateArithmeticWithTimezone(DateArithmeticTestCase):
FILE: tests/utils/trontimespec_test.py
class TestGetTime (line 11) | class TestGetTime(TestCase):
method test_get_time (line 12) | def test_get_time(self):
method test_get_time_invalid_time (line 16) | def test_get_time_invalid_time(self):
class TestTimeSpecification (line 21) | class TestTimeSpecification(TestCase):
method _cmp (line 22) | def _cmp(self, start_time, expected):
method test_get_match_months (line 27) | def test_get_match_months(self):
method test_get_match_monthdays (line 33) | def test_get_match_monthdays(self):
method test_get_match_weekdays (line 40) | def test_get_match_weekdays(self):
method test_next_month_generator (line 45) | def test_next_month_generator(self):
method test_next_day_monthdays (line 51) | def test_next_day_monthdays(self):
method test_next_day_monthdays_with_last (line 59) | def test_next_day_monthdays_with_last(self):
method test_next_day_weekdays (line 64) | def test_next_day_weekdays(self):
method test_next_day_weekdays_with_ordinals (line 72) | def test_next_day_weekdays_with_ordinals(self):
method test_next_time_timestr (line 83) | def test_next_time_timestr(self):
method test_next_time_hours (line 94) | def test_next_time_hours(self):
method test_next_time_minutes (line 105) | def test_next_time_minutes(self):
method test_next_time_hours_and_minutes_and_seconds (line 119) | def test_next_time_hours_and_minutes_and_seconds(self):
method test_get_match_dst_spring_forward (line 134) | def test_get_match_dst_spring_forward(self):
method test_get_match_dst_fall_back (line 147) | def test_get_match_dst_fall_back(self):
FILE: tools/action_dag_diagram.py
function parse_args (line 17) | def parse_args():
function build_diagram (line 39) | def build_diagram(job_config):
function get_job (line 51) | def get_job(config_container, namespace, job_name):
FILE: tools/compress_json.py
function get_dynamodb_table (line 30) | def get_dynamodb_table(
function get_dynamodb_client (line 37) | def get_dynamodb_client(
function scan_keys (line 45) | def scan_keys(source_table: ServiceResource) -> set[str]:
function resolve_keys (line 65) | def resolve_keys(args, parser, source_table: ServiceResource) -> list[str]:
function is_compressed (line 90) | def is_compressed(json_val) -> bool:
function get_json_val_bytes (line 106) | def get_json_val_bytes(json_val) -> bytes:
function classify_item (line 115) | def classify_item(item: dict) -> str:
function compress_json_for_key (line 133) | def compress_json_for_key(
function verify_compressed_json_for_key (line 305) | def verify_compressed_json_for_key(source_table: ServiceResource, key: s...
function delete_pickle_for_key (line 369) | def delete_pickle_for_key(source_table: ServiceResource, key: str, dry_r...
function cmd_compress (line 420) | def cmd_compress(args, source_table: ServiceResource, client, table_name...
function cmd_delete_pickles (line 503) | def cmd_delete_pickles(args, source_table: ServiceResource, keys: list[s...
function cmd_status (line 554) | def cmd_status(args, source_table: ServiceResource) -> None:
function add_key_arguments (line 591) | def add_key_arguments(subparser: argparse.ArgumentParser) -> None:
function main (line 610) | def main():
FILE: tools/inspect_serialized_state.py
function parse_options (line 17) | def parse_options():
function get_container (line 33) | def get_container(config_path):
function get_state (line 38) | def get_state(container):
function format_date (line 45) | def format_date(date_string):
function format_jobs (line 49) | def format_jobs(job_states):
function display_report (line 67) | def display_report(state_config, job_states):
function main (line 74) | def main(config_path, working_dir):
FILE: tools/migration/migrate_config_0.2_to_0.3.py
class Loader (line 18) | class Loader(yaml.Loader):
method compose_document (line 21) | def compose_document(self):
function strip_tags (line 28) | def strip_tags(source):
function name_from_doc (line 33) | def name_from_doc(doc):
function warn_node_pools (line 48) | def warn_node_pools(content):
function warn_requires_list (line 64) | def warn_requires_list(content):
function create_loader (line 89) | def create_loader(content):
function build_anchor_mapping (line 96) | def build_anchor_mapping(content):
function update_references (line 106) | def update_references(content):
function convert (line 130) | def convert(source, dest):
FILE: tools/migration/migrate_config_0.5.1_to_0.5.2.py
function parse_options (line 16) | def parse_options():
function main (line 33) | def main(source, dest):
FILE: tools/migration/migrate_state.py
function parse_options (line 26) | def parse_options():
function get_state_manager_from_config (line 64) | def get_state_manager_from_config(config_path, working_dir):
function get_current_config (line 73) | def get_current_config(config_path):
function add_namespaces (line 78) | def add_namespaces(state_data):
function strip_namespace (line 82) | def strip_namespace(names):
function convert_state (line 86) | def convert_state(opts):
FILE: tools/migration/migrate_state_1.3.15_to_1.4.0.py
function parse_args (line 10) | def parse_args():
function create_job_runs_for_job (line 31) | def create_job_runs_for_job(state_manager, job_name, job_state):
function move_job_runs_to_job (line 43) | def move_job_runs_to_job(state_manager, job_name, job_state):
function update_state (line 51) | def update_state(state_manager, job_names, back):
function migrate_state (line 60) | def migrate_state(config_path, working_dir, back):
FILE: tools/pickles_to_json.py
function get_dynamodb_table (line 20) | def get_dynamodb_table(
function get_all_jobs (line 34) | def get_all_jobs(source_table: ServiceResource) -> list[str]:
function get_job_names (line 45) | def get_job_names(base_url: str) -> list[str]:
function combine_pickle_partitions (line 63) | def combine_pickle_partitions(source_table: ServiceResource, key: str) -...
function dump_pickle_key (line 85) | def dump_pickle_key(source_table: ServiceResource, key: str) -> None:
function dump_pickle_keys (line 102) | def dump_pickle_keys(source_table: ServiceResource, keys: list[str]) -> ...
function dump_json_key (line 112) | def dump_json_key(source_table: ServiceResource, key: str) -> None:
function dump_json_keys (line 129) | def dump_json_keys(source_table: ServiceResource, keys: list[str]) -> None:
function delete_keys (line 140) | def delete_keys(source_table: ServiceResource, keys: list[str]) -> None:
function get_num_partitions (line 164) | def get_num_partitions(source_table: ServiceResource, key: str) -> int:
function combine_json_partitions (line 180) | def combine_json_partitions(source_table: ServiceResource, key: str) -> ...
function convert_pickle_to_json_and_update_table (line 207) | def convert_pickle_to_json_and_update_table(source_table: ServiceResourc...
function convert_pickles_to_json_and_update_table (line 253) | def convert_pickles_to_json_and_update_table(
function scan_table (line 325) | def scan_table(source_table: ServiceResource) -> list[dict]:
function main (line 340) | def main():
FILE: tools/sync_tron_state_from_k8s.py
function limit_size_with_hash (line 41) | def limit_size_with_hash(name: str, limit: int = 63, suffix: int = 4) ->...
function parse_args (line 57) | def parse_args():
function fetch_pods (line 113) | def fetch_pods(kubeconfig_path: str, kubecontext: str | None) -> dict[st...
function get_tron_state_from_api (line 127) | def get_tron_state_from_api(tron_server: str, num_runs: int = 100) -> li...
function get_matching_pod (line 153) | def get_matching_pod(action_run: dict[str, Any], pods: dict[str, V1Pod])...
function get_desired_state_from_pod (line 178) | def get_desired_state_from_pod(pod: V1Pod) -> str:
function update_tron_from_pods (line 183) | def update_tron_from_pods(
FILE: tron/actioncommand.py
class ActionCommand (line 18) | class ActionCommand(Observable):
method __init__ (line 54) | def __init__(self, id, command, serializer=None):
method state (line 70) | def state(self):
method transition_and_notify (line 73) | def transition_and_notify(self, target):
method started (line 78) | def started(self):
method exited (line 83) | def exited(self, exit_status):
method write_stderr (line 89) | def write_stderr(self, value):
method write_stdout (line 92) | def write_stdout(self, value):
method done (line 95) | def done(self):
method handle_errback (line 101) | def handle_errback(self, result):
method is_unknown (line 111) | def is_unknown(self):
method is_failed (line 115) | def is_failed(self):
method is_complete (line 119) | def is_complete(self):
method is_done (line 124) | def is_done(self):
method __repr__ (line 131) | def __repr__(self):
class StringBufferStore (line 135) | class StringBufferStore:
method __init__ (line 140) | def __init__(self):
method open (line 143) | def open(self, name):
method clear (line 146) | def clear(self):
class NoActionRunnerFactory (line 151) | class NoActionRunnerFactory:
method create (line 155) | def create(cls, id, command, serializer):
method build_stop_action_command (line 159) | def build_stop_action_command(cls, _id, _command):
method from_json (line 164) | def from_json():
method to_json (line 168) | def to_json():
class SubprocessActionRunnerFactory (line 172) | class SubprocessActionRunnerFactory(Persistable):
method __init__ (line 178) | def __init__(self, status_path, exec_path):
method from_config (line 183) | def from_config(cls, config):
method create (line 186) | def create(self, id, command, serializer):
method build_command (line 190) | def build_command(self, id, command, exec_name):
method build_stop_action_command (line 195) | def build_stop_action_command(self, id, command):
method __eq__ (line 200) | def __eq__(self, other):
method __ne__ (line 207) | def __ne__(self, other):
method from_json (line 211) | def from_json(state_data: str) -> dict[str, Any]:
method to_json (line 224) | def to_json(state_data: dict) -> str:
function create_action_runner_factory_from_config (line 240) | def create_action_runner_factory_from_config(config):
FILE: tron/api/adapter.py
class ReprAdapter (line 26) | class ReprAdapter:
method __init__ (line 32) | def __init__(self, internal_obj):
method _get_field_names (line 37) | def _get_field_names(self):
method _get_translation_mapping (line 40) | def _get_translation_mapping(self):
method get_repr (line 43) | def get_repr(self):
function adapt_many (line 50) | def adapt_many(adapter_class, seq, *args, **kwargs):
function toggle_flag (line 54) | def toggle_flag(
class RunAdapter (line 80) | class RunAdapter(ReprAdapter):
method get_state (line 83) | def get_state(self):
method get_node (line 86) | def get_node(self):
method get_duration (line 89) | def get_duration(self):
class ActionRunAdapter (line 94) | class ActionRunAdapter(RunAdapter):
method __init__ (line 128) | def __init__(
method get_raw_command (line 144) | def get_raw_command(self):
method get_command (line 147) | def get_command(self):
method get_requirements (line 151) | def get_requirements(self):
method _get_serializer (line 156) | def _get_serializer(self, path: str | None = None) -> filehandler.Outp...
method _get_alternate_output_paths (line 160) | def _get_alternate_output_paths(self):
method get_meta (line 182) | def get_meta(self) -> list[str]:
method get_stdout (line 198) | def get_stdout(self) -> list[str]:
method get_stderr (line 240) | def get_stderr(self) -> list[str]:
method get_job_name (line 281) | def get_job_name(self):
method get_run_num (line 284) | def get_run_num(self):
method get_retries_delay (line 287) | def get_retries_delay(self):
method get_in_delay (line 291) | def get_in_delay(self):
method get_triggered_by (line 295) | def get_triggered_by(self) -> str:
method get_trigger_downstreams (line 300) | def get_trigger_downstreams(self) -> str:
class ActionGraphAdapter (line 305) | class ActionGraphAdapter:
method __init__ (line 306) | def __init__(self, action_graph):
method get_repr (line 309) | def get_repr(self):
class ActionRunGraphAdapter (line 322) | class ActionRunGraphAdapter:
method __init__ (line 323) | def __init__(self, action_run_collection):
method get_repr (line 326) | def get_repr(self):
class JobRunAdapter (line 357) | class JobRunAdapter(RunAdapter):
method __init__ (line 377) | def __init__(
method get_url (line 387) | def get_url(self):
method get_runs (line 391) | def get_runs(self):
method get_action_graph (line 395) | def get_action_graph(self):
class JobAdapter (line 399) | class JobAdapter(ReprAdapter):
method __init__ (line 418) | def __init__(
method get_name (line 434) | def get_name(self):
method get_monitoring (line 437) | def get_monitoring(self):
method get_scheduler (line 440) | def get_scheduler(self):
method get_action_names (line 443) | def get_action_names(self):
method get_node_pool (line 447) | def get_node_pool(self):
method get_last_success (line 450) | def get_last_success(self):
method get_next_run (line 454) | def get_next_run(self):
method get_url (line 458) | def get_url(self):
method get_runs (line 462) | def get_runs(self):
method get_max_runtime (line 470) | def get_max_runtime(self):
method get_expected_runtime (line 473) | def get_expected_runtime(self):
method get_actions_expected_runtime (line 476) | def get_actions_expected_runtime(self):
method get_action_graph (line 480) | def get_action_graph(self):
class JobIndexAdapter (line 484) | class JobIndexAdapter(ReprAdapter):
method get_name (line 488) | def get_name(self):
method get_actions (line 491) | def get_actions(self):
class SchedulerAdapter (line 501) | class SchedulerAdapter(ReprAdapter):
method get_value (line 505) | def get_value(self):
method get_type (line 508) | def get_type(self):
method get_jitter (line 511) | def get_jitter(self):
class EventAdapter (line 515) | class EventAdapter(ReprAdapter):
method get_level (line 520) | def get_level(self):
class NodeAdapter (line 524) | class NodeAdapter(ReprAdapter):
class NodePoolAdapter (line 528) | class NodePoolAdapter(ReprAdapter):
method get_name (line 531) | def get_name(self):
method get_nodes (line 534) | def get_nodes(self):
FILE: tron/api/async_resource.py
function report_resource_request (line 10) | def report_resource_request(resource, request, duration_ms):
class AsyncResource (line 18) | class AsyncResource:
method finish (line 24) | def finish(result, request, resource):
method process (line 31) | def process(fn, resource, request):
method bounded (line 39) | def bounded(fn):
method exclusive (line 54) | def exclusive(fn):
FILE: tron/api/auth.py
class AuthorizationOutcome (line 18) | class AuthorizationOutcome(NamedTuple):
class AuthorizationFilter (line 23) | class AuthorizationFilter:
method __init__ (line 26) | def __init__(self, endpoint: str, enforce: bool):
method get_from_env (line 38) | def get_from_env(cls) -> "AuthorizationFilter":
method is_request_authorized (line 44) | def is_request_authorized(self, request: Request) -> AuthorizationOutc...
method _is_request_authorized_impl (line 65) | def _is_request_authorized_impl(
method _extract_service_from_path (line 109) | def _extract_service_from_path(path: str) -> str | None:
FILE: tron/api/controller.py
class UnknownCommandError (line 20) | class UnknownCommandError(Exception):
class InvalidCommandForActionState (line 24) | class InvalidCommandForActionState(Exception):
method __init__ (line 30) | def __init__(self, command: str, action_name: str, action_state: str) ...
class JobCollectionController (line 38) | class JobCollectionController:
method __init__ (line 39) | def __init__(self, job_collection):
method handle_command (line 42) | def handle_command(self, command, old_name=None, new_name=None):
class ActionRunController (line 53) | class ActionRunController:
method __init__ (line 67) | def __init__(self, action_run: ActionRun, job_run: JobRun) -> None:
method handle_command (line 71) | def handle_command(self, command, **kwargs):
method handle_termination (line 100) | def handle_termination(self, command):
method handle_retry (line 112) | def handle_retry(self, original_command):
class JobRunController (line 123) | class JobRunController:
method __init__ (line 127) | def __init__(self, job_run, job_scheduler):
method handle_command (line 131) | def handle_command(self, command):
class JobController (line 155) | class JobController:
method __init__ (line 156) | def __init__(self, job_scheduler):
method handle_command (line 159) | def handle_command(self, command, run_time=None):
class ConfigResponse (line 186) | class ConfigResponse(TypedDict):
class ConfigController (line 191) | class ConfigController:
method __init__ (line 198) | def __init__(self, mcp: "MasterControlProgram") -> None:
method _get_config_content (line 202) | def _get_config_content(self, name: str) -> str:
method read_config (line 207) | def read_config(self, name: str) -> ConfigResponse:
method read_all_configs (line 212) | def read_all_configs(self) -> dict[str, ConfigResponse]:
method check_config (line 224) | def check_config(self, name, content, config_hash):
method update_config (line 235) | def update_config(self, name, content, config_hash):
method delete_config (line 256) | def delete_config(self, name, content, config_hash):
method get_namespaces (line 272) | def get_namespaces(self):
class EventsController (line 276) | class EventsController:
method publish (line 279) | def publish(self, event):
method discard (line 295) | def discard(self, event):
method info (line 306) | def info(self):
FILE: tron/api/requestargs.py
function get_integer (line 8) | def get_integer(request, key):
function get_string (line 19) | def get_string(request, key):
function get_bool (line 37) | def get_bool(request, key, default=None):
function get_datetime (line 46) | def get_datetime(request, key):
FILE: tron/api/resource.py
class JSONEncoder (line 33) | class JSONEncoder(json.JSONEncoder):
method default (line 36) | def default(self, o):
function respond (line 49) | def respond(request, response, code=None, headers=None):
function handle_command (line 77) | def handle_command(request, api_controller, obj, **kwargs):
class AuthenticatedResource (line 105) | class AuthenticatedResource(resource.Resource):
method render (line 106) | def render(self, request):
class ErrorResource (line 119) | class ErrorResource(resource.Resource):
method __init__ (line 123) | def __init__(self, error="No Such Resource", code=http.NOT_FOUND):
method render_GET (line 129) | def render_GET(self, request):
method render_POST (line 133) | def render_POST(self, request):
method getChild (line 136) | def getChild(self, chnam, request):
function resource_from_collection (line 141) | def resource_from_collection(collection, name, child_resource):
class ActionRunResource (line 151) | class ActionRunResource(AuthenticatedResource):
method __init__ (line 155) | def __init__(self, action_run, job_run):
method render_GET (line 163) | def render_GET(self, request):
method render_POST (line 176) | def render_POST(self, request):
class JobRunResource (line 186) | class JobRunResource(AuthenticatedResource):
method __init__ (line 187) | def __init__(self, job_run, job_scheduler):
method getChild (line 193) | def getChild(self, action_name, _):
method render_GET (line 209) | def render_GET(self, request):
method render_POST (line 220) | def render_POST(self, request):
function is_negative_int (line 224) | def is_negative_int(string):
class JobResource (line 228) | class JobResource(AuthenticatedResource):
method __init__ (line 229) | def __init__(self, job_scheduler):
method get_run_from_identifier (line 234) | def get_run_from_identifier(self, run_id):
method getChild (line 243) | def getChild(self, run_id, _):
method render_GET (line 262) | def render_GET(self, request):
method render_POST (line 279) | def render_POST(self, request):
class ActionRunHistoryResource (line 289) | class ActionRunHistoryResource(AuthenticatedResource):
method __init__ (line 293) | def __init__(self, action_runs):
method render_GET (line 298) | def render_GET(self, request):
class JobCollectionResource (line 305) | class JobCollectionResource(AuthenticatedResource):
method __init__ (line 306) | def __init__(self, job_collection):
method getChild (line 311) | def getChild(self, name, request):
method get_data (line 318) | def get_data(
method get_job_index (line 335) | def get_job_index(self):
method render_GET (line 343) | def render_GET(self, request):
method render_POST (line 375) | def render_POST(self, request):
class ConfigResource (line 387) | class ConfigResource(AuthenticatedResource):
method __init__ (line 392) | def __init__(self, master_control):
method get_config_index (line 396) | def get_config_index(self):
method render_GET (line 400) | def render_GET(self, request):
method render_POST (line 409) | def render_POST(self, request):
class StatusResource (line 442) | class StatusResource(resource.Resource):
method __init__ (line 446) | def __init__(self, master_control):
method render_GET (line 451) | def render_GET(self, request):
class MetricsResource (line 462) | class MetricsResource(resource.Resource):
method __init__ (line 466) | def __init__(self):
method render_GET (line 470) | def render_GET(self, request):
class EventsResource (line 474) | class EventsResource(AuthenticatedResource):
method __init__ (line 477) | def __init__(self):
method render_GET (line 482) | def render_GET(self, request):
method render_POST (line 487) | def render_POST(self, request):
class ApiRootResource (line 501) | class ApiRootResource(AuthenticatedResource):
method __init__ (line 502) | def __init__(self, mcp):
method render_GET (line 520) | def render_GET(self, request):
class RootResource (line 529) | class RootResource(resource.Resource):
method __init__ (line 530) | def __init__(self, mcp, web_path):
method render_GET (line 538) | def render_GET(self, request):
method __str__ (line 543) | def __str__(self):
class LogAdapter (line 547) | class LogAdapter:
method __init__ (line 548) | def __init__(self, logger):
method write (line 551) | def write(self, line):
method close (line 554) | def close(self):
class TronSite (line 558) | class TronSite(server.Site):
method create (line 564) | def create(cls, mcp, web_path):
method startFactory (line 567) | def startFactory(self):
method log (line 571) | def log(self, request):
method __repr__ (line 582) | def __repr__(self):
FILE: tron/bin/action_runner.py
class StatusFile (line 19) | class StatusFile:
method __init__ (line 22) | def __init__(self, filename):
method get_content (line 25) | def get_content(self, run_id, command, proc):
method wrap (line 36) | def wrap(self, command, run_id, proc):
function validate_output_dir (line 64) | def validate_output_dir(path):
function build_environment (line 76) | def build_environment(run_id, original_env=None):
function build_labels (line 96) | def build_labels(
function run_proc (line 120) | def run_proc(output_path, command, run_id, proc):
function parse_args (line 133) | def parse_args():
function run_command (line 150) | def run_command(command, run_id):
function stream (line 160) | def stream(source, dst):
function configure_logging (line 178) | def configure_logging(run_id, output_dir):
function main (line 187) | def main():
FILE: tron/bin/action_status.py
function get_field (line 14) | def get_field(field, status_file):
function print_status_file (line 20) | def print_status_file(status_file):
function send_signal (line 25) | def send_signal(signal_num, status_file):
function parse_args (line 44) | def parse_args():
function run_command (line 61) | def run_command(command, status_file):
function main (line 65) | def main():
FILE: tron/bin/check_tron_datastore_staleness.py
function get_last_run_time (line 21) | def get_last_run_time(job):
function parse_cli (line 34) | def parse_cli():
function read_config (line 67) | def read_config(args):
function main (line 71) | def main():
FILE: tron/bin/check_tron_jobs.py
class State (line 29) | class State(Enum):
function parse_cli (line 39) | def parse_cli():
function _timestamp_to_timeobj (line 72) | def _timestamp_to_timeobj(timestamp):
function _timestamp_to_shortdate (line 76) | def _timestamp_to_shortdate(timestamp, separator="."):
function compute_check_result_for_job_runs (line 83) | def compute_check_result_for_job_runs(client, job, job_content, url_inde...
function pretty_print_job (line 189) | def pretty_print_job(job_content):
function pretty_print_job_run (line 193) | def pretty_print_job_run(job_run):
function pretty_print_actions (line 198) | def pretty_print_actions(action_run):
function get_relevant_run_and_state (line 202) | def get_relevant_run_and_state(job_content):
function is_action_failed_or_unknown (line 238) | def is_action_failed_or_unknown(job_run):
function is_job_stuck (line 245) | def is_job_stuck(
function is_job_run_exceeding_expected_runtime (line 277) | def is_job_run_exceeding_expected_runtime(job_run, job_expected_runtime):
function is_action_run_exceeding_expected_runtime (line 293) | def is_action_run_exceeding_expected_runtime(
function get_relevant_action (line 309) | def get_relevant_action(*, action_runs, last_state, actions_expected_run...
function guess_realert_every (line 328) | def guess_realert_every(job):
function get_earliest_run_time_to_check (line 354) | def get_earliest_run_time_to_check(job_content, interval):
function sort_runs_by_interval (line 365) | def sort_runs_by_interval(job_content, interval="day", until=None):
function compute_check_result_for_job (line 407) | def compute_check_result_for_job(client, job, url_index):
function check_job (line 469) | def check_job(job, client, url_index):
function check_job_result (line 480) | def check_job_result(job, client, url_index, dry_run):
function main (line 498) | def main():
FILE: tron/bin/get_tron_metrics.py
function parse_cli (line 18) | def parse_cli():
function check_bin_exists (line 31) | def check_bin_exists(bin):
function send_data_metric (line 47) | def send_data_metric(name, metric_type, value, dimensions={}, dry_run=Fa...
function send_counter (line 91) | def send_counter(name, **kwargs):
function send_gauge (line 101) | def send_gauge(name, **kwargs):
function send_meter (line 111) | def send_meter(name, **kwargs):
function send_histogram (line 115) | def send_histogram(name, **kwargs):
function send_timer (line 122) | def send_timer(name, **kwargs):
function send_metrics (line 138) | def send_metrics(metrics, cluster=None, dry_run=False):
function main (line 157) | def main():
FILE: tron/bin/recover_batch.py
class StatusFileWatcher (line 18) | class StatusFileWatcher:
method __init__ (line 23) | def __init__(self, to_watch, callback):
function parse_args (line 29) | def parse_args():
function read_last_yaml_entries (line 37) | def read_last_yaml_entries(filename):
function notify (line 47) | def notify(notify_queue, ignored, filepath, mask):
function get_exit_code (line 54) | def get_exit_code(filepath):
function run (line 78) | def run(fpath):
FILE: tron/command_context.py
function build_context (line 11) | def build_context(object, parent):
function build_filled_context (line 18) | def build_filled_context(*context_objects):
class CommandContext (line 34) | class CommandContext:
method __init__ (line 45) | def __init__(self, base=None, next=None):
method get (line 54) | def get(self, name, default=None):
method __getitem__ (line 60) | def __getitem__(self, name):
method __eq__ (line 71) | def __eq__(self, other):
method __ne__ (line 74) | def __ne__(self, other):
class JobContext (line 78) | class JobContext:
method __init__ (line 81) | def __init__(self, job):
method name (line 85) | def name(self):
method __getitem__ (line 88) | def __getitem__(self, item):
method _get_date_spec_parts (line 106) | def _get_date_spec_parts(self, name):
method namespace (line 113) | def namespace(self):
class JobRunContext (line 117) | class JobRunContext:
method __init__ (line 118) | def __init__(self, job_run):
method runid (line 122) | def runid(self):
method manual (line 126) | def manual(self):
method cleanup_job_status (line 130) | def cleanup_job_status(self):
method __getitem__ (line 140) | def __getitem__(self, name):
class ActionRunContext (line 183) | class ActionRunContext:
method __init__ (line 186) | def __init__(self, action_run):
method actionname (line 190) | def actionname(self):
method node (line 194) | def node(self):
class Filler (line 198) | class Filler:
method __getattr__ (line 204) | def __getattr__(self, _):
method __str__ (line 207) | def __str__(self):
method __mod__ (line 210) | def __mod__(self, _):
method __nonzero__ (line 213) | def __nonzero__(self):
method __bool__ (line 216) | def __bool__(self):
FILE: tron/commands/authentication.py
function get_instance_oidc_identity_token (line 11) | def get_instance_oidc_identity_token(role: str, ecosystem: str | None = ...
function get_and_cache_jwt_default (line 14) | def get_and_cache_jwt_default(client_id: str, refreshable: bool = False,...
function get_sso_auth_token (line 18) | def get_sso_auth_token(no_cache: bool = False) -> str:
function get_vault_auth_token (line 24) | def get_vault_auth_token() -> str:
function get_auth_token (line 30) | def get_auth_token(no_cache: bool = False) -> str:
FILE: tron/commands/backfill.py
function get_date_range (line 21) | def get_date_range(
function print_backfill_cmds (line 35) | def print_backfill_cmds(job: str, date_strs: list[str]) -> None:
function confirm_backfill (line 44) | def confirm_backfill(job: str, date_strs: list[str]) -> bool:
class BackfillRun (line 61) | class BackfillRun:
method __init__ (line 66) | def __init__(self, tron_client: client.Client, job_id: client.TronObje...
method run_time_str (line 75) | def run_time_str(self) -> str:
method run_until_completion (line 78) | async def run_until_completion(self) -> str:
method create (line 88) | async def create(self) -> str | None:
method get_run_id (line 128) | async def get_run_id(self) -> client.TronObjectIdentifier | None:
method sync_state (line 144) | async def sync_state(self) -> str:
method watch_until_completion (line 173) | async def watch_until_completion(self, poll_intv_s: int = DEFAULT_POLL...
method cancel (line 193) | async def cancel(self) -> bool:
function run_backfill_for_date_range (line 229) | async def run_backfill_for_date_range(
class DisplayBackfillRuns (line 293) | class DisplayBackfillRuns(display.TableDisplay):
function print_backfill_runs_table (line 303) | def print_backfill_runs_table(runs: list[BackfillRun]) -> None:
FILE: tron/commands/client.py
class RequestError (line 24) | class RequestError(ValueError):
function build_url_request (line 35) | def build_url_request(uri, data, headers=None, method=None):
function load_response_content (line 46) | def load_response_content(http_response):
function build_http_error_response (line 58) | def build_http_error_response(exc):
function request (line 75) | def request(uri, data=None, headers=None, method=None, user_attribution=...
function build_get_url (line 93) | def build_get_url(url, data=None):
function ensure_user_attribution (line 101) | def ensure_user_attribution(headers: dict[str, str]) -> dict[str, str]:
class Client (line 109) | class Client:
method __init__ (line 112) | def __init__(self, url_base, cluster_name=None, user_attribution=False):
method status (line 122) | def status(self):
method metrics (line 125) | def metrics(self):
method config (line 128) | def config(
method home (line 148) | def home(self):
method get_url (line 153) | def get_url(self, identifier):
method jobs (line 156) | def jobs(
method job (line 171) | def job(self, job_url, include_action_runs=False, count=0):
method job_runs (line 178) | def job_runs(self, url, include_runs=True, include_graph=False):
method action_runs (line 185) | def action_runs(self, action_run_url, num_lines=0):
method http_get (line 193) | def http_get(self, url, data=None):
method request (line 196) | def request(self, url, data=None):
function build_api_url (line 207) | def build_api_url(resource, identifier_parts):
function split_identifier (line 211) | def split_identifier(identifier):
function get_job_url (line 215) | def get_job_url(identifier):
class TronObjectType (line 219) | class TronObjectType:
function first (line 240) | def first(seq):
function get_object_type_from_identifier (line 245) | def get_object_type_from_identifier(url_index, identifier):
FILE: tron/commands/cmd_utils.py
class ExitCode (line 16) | class ExitCode:
function get_default_server (line 49) | def get_default_server():
function filter_jobs_actions_runs (line 53) | def filter_jobs_actions_runs(prefix, inputs):
function tron_jobs_completer (line 72) | def tron_jobs_completer(prefix, **kwargs):
function build_option_parser (line 94) | def build_option_parser(usage=None, epilog=None):
function get_client_config (line 134) | def get_client_config():
function load_config (line 147) | def load_config(options):
function read_config (line 170) | def read_config(filename=CONFIG_FILE_NAME):
function write_config (line 179) | def write_config(config):
function save_config (line 184) | def save_config(options):
function setup_logging (line 193) | def setup_logging(options: argparse.Namespace) -> int:
function suggest_possibilities (line 212) | def suggest_possibilities(word, possibilities, max_suggestions=6):
function warning_output (line 226) | def warning_output(text: str, color: str = COLOR_RED) -> str:
FILE: tron/commands/display.py
class Color (line 16) | class Color:
method enable (line 40) | def enable(cls):
method set (line 49) | def set(cls, color_name, text):
method toggle (line 59) | def toggle(cls, enable):
class TableDisplay (line 63) | class TableDisplay:
method __init__ (line 97) | def __init__(self, sort_index=0):
method banner (line 101) | def banner(self):
method header (line 109) | def header(self):
method footer (line 113) | def footer(self):
method color (line 116) | def color(self, col, field):
method sorted_fields (line 119) | def sorted_fields(self, values):
method format_row (line 122) | def format_row(self, fields):
method get_field_width (line 129) | def get_field_width(self, field_idx):
method trim_value (line 132) | def trim_value(self, field_idx, value):
method format_value (line 139) | def format_value(self, field_idx, value):
method output (line 142) | def output(self):
method post_row (line 147) | def post_row(self, row):
method row_color (line 150) | def row_color(self, row):
method rows (line 153) | def rows(self):
method store_data (line 160) | def store_data(self, data):
method update_column_widths (line 163) | def update_column_widths(self):
method calculate_width (line 169) | def calculate_width(self, field_idx):
method format (line 177) | def format(self, data):
function add_color_for_state (line 194) | def add_color_for_state(state):
function format_fields (line 208) | def format_fields(display_obj, content):
function format_job_details (line 226) | def format_job_details(job_content):
function format_action_run_details (line 235) | def format_action_run_details(content, stdout=True, stderr=True):
class DisplayJobRuns (line 247) | class DisplayJobRuns(TableDisplay):
method format_value (line 272) | def format_value(self, field_idx, value):
method row_color (line 284) | def row_color(self, fields):
method post_row (line 287) | def post_row(self, row):
class DisplayJobs (line 301) | class DisplayJobs(TableDisplay):
method format_value (line 325) | def format_value(self, field_idx, value):
class DisplayActionRuns (line 332) | class DisplayActionRuns(TableDisplay):
method __init__ (line 361) | def __init__(self):
method banner (line 365) | def banner(self):
method format_value (line 369) | def format_value(self, field_idx, value):
method row_color (line 380) | def row_color(self, fields):
method store_data (line 383) | def store_data(self, data):
method rows (line 387) | def rows(self):
function display_node (line 398) | def display_node(source, _=None):
function display_node_pool (line 404) | def display_node_pool(source, _=None):
function display_scheduler (line 410) | def display_scheduler(source, _=None):
function display_state_delayed (line 416) | def display_state_delayed(_, obj):
function view_with_less (line 434) | def view_with_less(content, color=True):
FILE: tron/commands/retry.py
function parse_deps_timeout (line 18) | def parse_deps_timeout(duration: str) -> int:
class RetryAction (line 34) | class RetryAction:
method __init__ (line 42) | def __init__(
method job_run_name (line 62) | def job_run_name(self) -> str:
method action_name (line 66) | def action_name(self) -> str:
method status (line 70) | def status(self) -> str:
method succeeded (line 83) | def succeeded(self) -> bool:
method _validate_action_name (line 86) | def _validate_action_name(self, full_action_name: str) -> client.TronO...
method _get_required_action_indices (line 95) | def _get_required_action_indices(self) -> dict[str, int]:
method _log (line 107) | def _log(self, msg: str) -> None:
method can_retry (line 110) | async def can_retry(self) -> bool:
method check_trigger_statuses (line 131) | async def check_trigger_statuses(self) -> dict[str, bool]:
method check_required_actions_statuses (line 153) | async def check_required_actions_statuses(self) -> dict[str, bool]:
method wait_and_retry (line 166) | async def wait_and_retry(
method wait_for_deps (line 188) | async def wait_for_deps(
method issue_retry (line 209) | async def issue_retry(self) -> bool:
function retry_actions (line 230) | def retry_actions(
class DisplayRetries (line 253) | class DisplayRetries(display.TableDisplay):
function print_retries_table (line 263) | def print_retries_table(retries: list[RetryAction]) -> None:
FILE: tron/config/__init__.py
class ConfigError (line 1) | class ConfigError(Exception):
FILE: tron/config/config_parse.py
function build_format_string_validator (line 67) | def build_format_string_validator(context_object):
function valid_output_stream_dir (line 94) | def valid_output_stream_dir(output_dir, config_context):
function valid_identity_file (line 117) | def valid_identity_file(file_path, config_context):
function valid_known_hosts_file (line 133) | def valid_known_hosts_file(file_path, config_context):
function valid_command_context (line 145) | def valid_command_context(context, config_context):
function valid_time_zone (line 150) | def valid_time_zone(tz, config_context):
function valid_node_name (line 160) | def valid_node_name(value, config_context):
function valid_master_address (line 168) | def valid_master_address(value, config_context):
function valid_k8s_master_address (line 203) | def valid_k8s_master_address(value: str, config_context: ConfigContext) ...
class ValidateConstraint (line 238) | class ValidateConstraint(Validator):
class ValidateDockerParameter (line 250) | class ValidateDockerParameter(Validator):
class ValidateVolume (line 261) | class ValidateVolume(Validator):
class ValidateSecretSource (line 273) | class ValidateSecretSource(Validator):
function valid_permission_mode (line 284) | def valid_permission_mode(value: str | int, config_context: ConfigContex...
class ValidateSecretVolumeItem (line 298) | class ValidateSecretVolumeItem(Validator):
class ValidateSecretVolume (line 311) | class ValidateSecretVolume(Validator):
method post_validation (line 328) | def post_validation(self, valid_input, config_context):
class ValidateProjectedSAVolume (line 366) | class ValidateProjectedSAVolume(Validator):
class ValidateFieldSelectorSource (line 382) | class ValidateFieldSelectorSource(Validator):
function _valid_node_affinity_operator (line 392) | def _valid_node_affinity_operator(value: str, config_context: ConfigCont...
class ValidateNodeAffinity (line 400) | class ValidateNodeAffinity(Validator):
function _valid_when_unsatisfiable (line 412) | def _valid_when_unsatisfiable(value: str, config_context: ConfigContext)...
function _valid_topology_spread_label_selector (line 420) | def _valid_topology_spread_label_selector(value: dict[str, str], config_...
class ValidateTopologySpreadConstraints (line 434) | class ValidateTopologySpreadConstraints(Validator):
class ValidateSSHOptions (line 447) | class ValidateSSHOptions(Validator):
method post_validation (line 481) | def post_validation(self, valid_input, config_context):
class ValidateNode (line 492) | class ValidateNode(Validator):
method do_shortcut (line 506) | def do_shortcut(self, node):
method set_defaults (line 511) | def set_defaults(self, output_dict, config_context):
class ValidateNodePool (line 519) | class ValidateNodePool(Validator):
method cast (line 526) | def cast(self, node_pool, _context):
method set_defaults (line 531) | def set_defaults(self, node_pool, _):
function valid_action_name (line 538) | def valid_action_name(value, config_context):
function valid_mesos_action (line 553) | def valid_mesos_action(action, config_context):
function valid_kubernetes_action (line 566) | def valid_kubernetes_action(action, config_context):
function valid_trigger_downstreams (line 579) | def valid_trigger_downstreams(trigger_downstreams, config_context):
class ValidateAction (line 585) | class ValidateAction(Validator):
method post_validation (line 668) | def post_validation(self, action, config_context):
function valid_cleanup_action_name (line 676) | def valid_cleanup_action_name(value, config_context):
class ValidateCleanupAction (line 683) | class ValidateCleanupAction(Validator):
method post_validation (line 758) | def post_validation(self, action, config_context):
class ValidateJob (line 766) | class ValidateJob(Validator):
method cast (line 802) | def cast(self, in_dict, config_context):
method _validate_dependencies (line 807) | def _validate_dependencies(
method post_validation (line 845) | def post_validation(self, job, config_context):
class ValidateActionRunner (line 854) | class ValidateActionRunner(Validator):
class ValidateStatePersistence (line 870) | class ValidateStatePersistence(Validator):
method post_validation (line 888) | def post_validation(self, config, config_context):
class ValidateMesos (line 915) | class ValidateMesos(Validator):
class ValidateKubernetes (line 945) | class ValidateKubernetes(Validator):
function validate_jobs (line 967) | def validate_jobs(config, config_context):
class ValidateConfig (line 988) | class ValidateConfig(Validator):
method validate_node_pool_nodes (line 1031) | def validate_node_pool_nodes(self, config):
method post_validation (line 1042) | def post_validation(self, config, _):
class ValidateNamedConfig (line 1062) | class ValidateNamedConfig(Validator):
method post_validation (line 1076) | def post_validation(self, config, config_context):
function validate_fragment (line 1084) | def validate_fragment(name, fragment, master_config=None):
function get_nodes_from_master_namespace (line 1098) | def get_nodes_from_master_namespace(master):
function validate_config_mapping (line 1102) | def validate_config_mapping(config_mapping):
class ConfigContainer (line 1124) | class ConfigContainer:
method __init__ (line 1127) | def __init__(self, config_mapping):
method items (line 1130) | def items(self):
method create (line 1134) | def create(cls, config_mapping):
method get_job_names (line 1138) | def get_job_names(self):
method get_jobs (line 1144) | def get_jobs(self):
method get_master (line 1149) | def get_master(self):
method get_node_names (line 1152) | def get_node_names(self):
method __getitem__ (line 1155) | def __getitem__(self, name):
method __contains__ (line 1158) | def __contains__(self, name):
FILE: tron/config/config_utils.py
class StringFormatter (line 15) | class StringFormatter(Formatter):
method __init__ (line 16) | def __init__(self, context=None):
method get_value (line 20) | def get_value(self, key, args, kwds):
class UniqueNameDict (line 30) | class UniqueNameDict(dict):
method __init__ (line 38) | def __init__(self, fmt_string):
method __setitem__ (line 42) | def __setitem__(self, key, value):
function unique_names (line 48) | def unique_names(fmt_string, *seqs):
function build_type_validator (line 56) | def build_type_validator(validator, error_fmt):
function valid_number (line 75) | def valid_number(type_func, value, config_context, allow_negative=False):
function build_enum_validator (line 119) | def build_enum_validator(enum):
function build_real_enum_validator (line 125) | def build_real_enum_validator(enum):
function valid_time (line 137) | def valid_time(value, config_context):
function valid_time_delta (line 161) | def valid_time_delta(value, config_context):
function valid_name_identifier (line 175) | def valid_name_identifier(value, config_context):
function build_list_of_type_validator (line 182) | def build_list_of_type_validator(item_validator, allow_empty=False):
function build_dict_name_validator (line 199) | def build_dict_name_validator(item_validator, allow_empty=False):
function build_dict_value_validator (line 223) | def build_dict_value_validator(item_validator, allow_empty=False):
class ConfigContext (line 238) | class ConfigContext:
method __init__ (line 246) | def __init__(self, path, nodes, command_context, namespace):
method build_child_context (line 252) | def build_child_context(self, path):
class PartialConfigContext (line 259) | class PartialConfigContext:
method __init__ (line 268) | def __init__(self, path, namespace):
method build_child_context (line 272) | def build_child_context(self, path):
class NullConfigContext (line 277) | class NullConfigContext:
method build_child_context (line 285) | def build_child_context(_):
class Validator (line 290) | class Validator:
method validate (line 300) | def validate(self, in_dict, config_context):
method __call__ (line 317) | def __call__(self, in_dict, config_context=NullConfigContext):
method type_name (line 321) | def type_name(self):
method all_keys (line 329) | def all_keys(self):
method do_shortcut (line 332) | def do_shortcut(self, in_dict):
method cast (line 339) | def cast(self, in_dict, _):
method build_context (line 345) | def build_context(self, in_dict, config_context):
method validate_required_keys (line 349) | def validate_required_keys(self, in_dict):
method validate_extra_keys (line 364) | def validate_extra_keys(self, in_dict):
method set_defaults (line 374) | def set_defaults(self, output_dict, _config_context):
method path_name (line 381) | def path_name(self, name=None):
method post_validation (line 384) | def post_validation(self, valid_input, config_context):
method build_config (line 390) | def build_config(self, in_dict, config_context):
method validate_contents (line 400) | def validate_contents(self, input, config_context):
FILE: tron/config/manager.py
function from_string (line 17) | def from_string(content):
function write (line 24) | def write(path, content):
function read (line 29) | def read(path):
function write_raw (line 34) | def write_raw(path, content):
function read_raw (line 41) | def read_raw(path: str) -> str:
function hash_digest (line 46) | def hash_digest(content: str | bytes) -> str:
class ManifestFile (line 52) | class ManifestFile:
method __init__ (line 57) | def __init__(self, path):
method create (line 60) | def create(self):
method add (line 68) | def add(self, name, filename):
method delete (line 73) | def delete(self, name):
method get_file_mapping (line 83) | def get_file_mapping(self):
method get_file_name (line 86) | def get_file_name(self, name):
method __contains__ (line 89) | def __contains__(self, name):
class ConfigManager (line 93) | class ConfigManager:
method __init__ (line 98) | def __init__(self, config_path, manifest=None):
method build_file_path (line 103) | def build_file_path(self, name):
method read_raw_config (line 107) | def read_raw_config(self, name: str = schema.MASTER_NAMESPACE) -> str:
method write_config (line 112) | def write_config(self, name: str, content: str) -> None:
method delete_config (line 128) | def delete_config(self, name: str) -> None:
method get_filename_from_manifest (line 141) | def get_filename_from_manifest(self, name):
method validate_with_fragment (line 149) | def validate_with_fragment(
method get_config_name_mapping (line 169) | def get_config_name_mapping(self):
method load (line 176) | def load(self):
method get_hash (line 182) | def get_hash(self, name: str) -> str:
method __contains__ (line 207) | def __contains__(self, name):
method get_namespaces (line 210) | def get_namespaces(self) -> list[str]:
function create_new_config (line 214) | def create_new_config(path, master_content):
FILE: tron/config/schedule_parse.py
class ScheduleParseError (line 36) | class ScheduleParseError(ConfigError):
function pad_sequence (line 40) | def pad_sequence(seq, size, padding=None):
function schedule_config_from_string (line 46) | def schedule_config_from_string(schedule, config_context):
function validate_generic_schedule_config (line 62) | def validate_generic_schedule_config(config, config_context):
function schedule_config_from_legacy_dict (line 67) | def schedule_config_from_legacy_dict(schedule, config_context):
function valid_schedule (line 80) | def valid_schedule(schedule, config_context):
function valid_daily_scheduler (line 91) | def valid_daily_scheduler(config, config_context):
function normalize_weekdays (line 118) | def normalize_weekdays(seq):
function day_canonicalization_map (line 122) | def day_canonicalization_map():
function month_canonicalization_map (line 162) | def month_canonicalization_map():
function build_groc_schedule_parser_re (line 180) | def build_groc_schedule_parser_re():
function _parse_number (line 240) | def _parse_number(day):
function parse_groc_expression (line 244) | def parse_groc_expression(config, config_context):
function valid_cron_scheduler (line 290) | def valid_cron_scheduler(config, config_context):
class ScheduleValidator (line 311) | class ScheduleValidator(config_utils.Validator):
FILE: tron/config/schema.py
function config_object_factory (line 16) | def config_object_factory(name, required=None, optional=None):
class ConfigSecretVolume (line 285) | class ConfigSecretVolume(_ConfigSecretVolume): # type: ignore
method _asdict (line 286) | def _asdict(self) -> dict:
class ExecutorTypes (line 347) | class ExecutorTypes(Enum):
FILE: tron/config/static_config.py
function load_yaml_file (line 10) | def load_yaml_file() -> None:
function build_configuration_watcher (line 14) | def build_configuration_watcher(filename: str, namespace: str) -> config...
function get_config_watcher (line 21) | def get_config_watcher() -> config.ConfigurationWatcher:
FILE: tron/core/action.py
class ActionCommandConfig (line 27) | class ActionCommandConfig(Persistable):
method state_data (line 55) | def state_data(self):
method copy (line 58) | def copy(self):
method from_json (line 62) | def from_json(
method to_json (line 108) | def to_json(state_data: dict) -> str:
class Action (line 178) | class Action:
method is_cleanup (line 195) | def is_cleanup(self):
method command (line 199) | def command(self):
method from_config (line 203) | def from_config(cls, config: ConfigAction) -> "Action":
FILE: tron/core/actiongraph.py
class ActionGraph (line 13) | class ActionGraph:
method __init__ (line 16) | def __init__(
method get_dependencies (line 30) | def get_dependencies(self, action_name: str, include_triggers: bool = ...
method names (line 42) | def names(self, include_triggers=False):
method expected_runtime (line 49) | def expected_runtime(self):
method __getitem__ (line 52) | def __getitem__(self, name):
method __eq__ (line 62) | def __eq__(self, other):
method __ne__ (line 69) | def __ne__(self, other):
FILE: tron/core/actionrun.py
class ActionRunFactory (line 64) | class ActionRunFactory:
method build_action_run_collection (line 70) | def build_action_run_collection(cls, job_run, action_runner):
method action_run_collection_from_state (line 85) | def action_run_collection_from_state(
method build_run_for_action (line 106) | def build_run_for_action(cls, job_run, action, action_runner):
method action_run_from_state (line 139) | def action_run_from_state(cls, job_run, state_data, cleanup=False):
class ActionRunAttempt (line 158) | class ActionRunAttempt(Persistable):
method exit (line 169) | def exit(self, exit_status, end_time=None):
method display_command (line 175) | def display_command(self):
method state_data (line 179) | def state_data(self):
method to_json (line 189) | def to_json(state_data: dict) -> str:
method from_json (line 216) | def from_json(state_data: str) -> dict[str, Any]: # TODO: use a Typed...
method from_state (line 237) | def from_state(cls, state_data):
class ActionRun (line 253) | class ActionRun(Observable, Persistable):
method __init__ (line 365) | def __init__(
method state (line 428) | def state(self) -> str:
method id (line 432) | def id(self):
method name (line 436) | def name(self):
method last_attempt (line 440) | def last_attempt(self):
method exit_statuses (line 446) | def exit_statuses(self):
method command (line 452) | def command(self):
method rendered_command (line 459) | def rendered_command(self):
method attempts_from_state (line 465) | def attempts_from_state(cls, state_data, command_config):
method from_state (line 496) | def from_state(
method start (line 563) | def start(self, original_command: bool = True) -> bool | ActionCommand...
method create_attempt (line 601) | def create_attempt(self, original_command=True):
method submit_command (line 615) | def submit_command(self, attempt: ActionRunAttempt) -> bool | ActionCo...
method stop (line 618) | def stop(self):
method kill (line 621) | def kill(self, final=True):
method recover (line 624) | def recover(self) -> ActionCommand | None:
method _done (line 627) | def _done(self, target: str, exit_status: int | None = 0) -> bool | None:
method retry (line 651) | def retry(self, original_command=True):
method start_after_delay (line 672) | def start_after_delay(self):
method restart (line 678) | def restart(self, original_command: bool = True) -> bool | ActionComma...
method fail (line 691) | def fail(self, exit_status=None):
method _exit_unsuccessful (line 697) | def _exit_unsuccessful(
method triggers_to_emit (line 731) | def triggers_to_emit(self) -> list[str]:
method emit_triggers (line 742) | def emit_triggers(self):
method rendered_triggers (line 754) | def rendered_triggers(self) -> list[str]:
method remaining_triggers (line 759) | def remaining_triggers(self):
method success (line 762) | def success(self) -> bool | None:
method fail_unknown (line 770) | def fail_unknown(self):
method cancel_delay (line 775) | def cancel_delay(self):
method state_data (line 783) | def state_data(self):
method from_json (line 815) | def from_json(
method to_json (line 854) | def to_json(state_data: dict) -> str:
method render_template (line 894) | def render_template(self, template):
method render_command (line 898) | def render_command(self, command):
method is_valid_command (line 907) | def is_valid_command(self, command):
method is_done (line 911) | def is_done(self):
method is_complete (line 915) | def is_complete(self):
method is_broken (line 919) | def is_broken(self):
method is_active (line 923) | def is_active(self):
method cleanup (line 926) | def cleanup(self):
method clear_trigger_timeout (line 933) | def clear_trigger_timeout(self):
method setup_subscriptions (line 938) | def setup_subscriptions(self):
method trigger_timeout_reached (line 956) | def trigger_timeout_reached(self):
method trigger_notify (line 966) | def trigger_notify(self, *_):
method is_blocked_on_trigger (line 972) | def is_blocked_on_trigger(self):
method clear_end_state (line 975) | def clear_end_state(self):
method __getattr__ (line 983) | def __getattr__(self, name: str) -> Callable[[], bool | None] | bool:
method __str__ (line 999) | def __str__(self):
method transition_and_notify (line 1002) | def transition_and_notify(self, target: str) -> bool | None:
class SSHActionRun (line 1009) | class SSHActionRun(ActionRun, Observer):
method __init__ (line 1012) | def __init__(self, *args, **kwargs):
method submit_command (line 1016) | def submit_command(self, attempt):
method stop (line 1026) | def stop(self):
method kill (line 1039) | def kill(self, final=True):
method build_action_command (line 1052) | def build_action_command(self, attempt):
method handle_unknown (line 1063) | def handle_unknown(self):
method recover (line 1079) | def recover(self) -> DelayedCall | Literal[True] | None: # type: igno...
method do_recover (line 1097) | def do_recover(self, delay: float) -> DelayedCall | Literal[True] | None:
method submit_recovery_command (line 1146) | def submit_recovery_command(
method handle_action_command_state_change (line 1163) | def handle_action_command_state_change(self, action_command, event, ev...
class MesosActionRun (line 1187) | class MesosActionRun(ActionRun, Observer):
method _create_mesos_task (line 1190) | def _create_mesos_task(
method submit_command (line 1213) | def submit_command(self, attempt):
method recover (line 1228) | def recover(self) -> MesosTask | None:
method stop (line 1268) | def stop(self):
method kill (line 1277) | def kill(self, final=True):
method _kil
Condensed preview — 347 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,787K chars).
[
{
"path": ".dockerignore",
"chars": 16,
"preview": ".tox\n.git\n.idea\n"
},
{
"path": ".github/workflows/ci.yml",
"chars": 2302,
"preview": "---\nname: tron-ci\non:\n push:\n branches:\n - master\n tags:\n - v*.*\n pull_request:\n release:\njobs:\n tox"
},
{
"path": ".github/workflows/security-review.yml",
"chars": 952,
"preview": "# Managed by terraform, do not edit manually\nname: Security Review\npermissions:\n pull-requests: write\n contents: read\n"
},
{
"path": ".gitignore",
"chars": 829,
"preview": "dist\nbuild\nMANIFEST\ntron.egg-info\n*.pyc\n*._*\n*.swp\n*.swo\ndocs/_build/\n.idea\n.vscode\n.fleet\ntron.iml\ndocs/images/\n*.dot\nt"
},
{
"path": ".pre-commit-config.yaml",
"chars": 1323,
"preview": "---\ndefault_language_version:\n python: python3.10\nrepos:\n - repo: https://github.com/pre-commit/pre-commit-hooks\n "
},
{
"path": ".pyautotest",
"chars": 28,
"preview": "test_runner_name: \"testify\"\n"
},
{
"path": ".readthedocs.yaml",
"chars": 1059,
"preview": "# Read the Docs configuration file for Sphinx projects\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html f"
},
{
"path": "AGENTS.md",
"chars": 3311,
"preview": "# AGENTS.md\n\nThis file provides guidance to AI coding agents working with code in this repository.\n\n## What is Tron?\n\nTr"
},
{
"path": "CODEOWNERS",
"chars": 155,
"preview": "# NOTE: \"we\" in this file will refer to the Compute Infrastructure team at Yelp\n* @Yelp/paasta\n#\n# prevent cheeky modifi"
},
{
"path": "LICENSE.txt",
"chars": 566,
"preview": "Copyright 2010-2012 Yelp\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file "
},
{
"path": "MANIFEST.in",
"chars": 286,
"preview": "include *.txt\ninclude *.md\ninclude Makefile\ninclude tron/default_config.yaml\ninclude tron/logging.conf\ninclude tron/name"
},
{
"path": "Makefile",
"chars": 4727,
"preview": "# Edit this release and run \"make release\"\nRELEASE=3.10.0\n\nSHELL=/bin/bash\n\nDOCKER_RUN = docker run -t -v $(CURDIR):/wor"
},
{
"path": "OWNERS",
"chars": 52,
"preview": "---\nteams:\n- Compute Infra <compute-infra@yelp.com>\n"
},
{
"path": "README.md",
"chars": 1658,
"preview": "Tron - Batch Scheduling System\n==============================\n\n[:\n def __init__(self):\n se"
},
{
"path": "contrib/namespace_cleanup.sh",
"chars": 1399,
"preview": "#/bin/bash\n\necosystem=\"stagef\"\n\nread -p \"Are you at tron-$ecosystem (y/n)?\" RES\necho\nif [ $RES = \"y\" ]; then\n #lo"
},
{
"path": "contrib/patch-config-loggers.diff",
"chars": 2833,
"preview": "--- a/debian/tron/opt/venvs/tron/lib/python3.10/site-packages/kubernetes/client/configuration.py\n+++ b/debian/tron/opt/v"
},
{
"path": "contrib/sync-from-yelp-prod.sh",
"chars": 247,
"preview": "#!/bin/bash\nrsync --exclude=.stderr --exclude=.stdout -aPv tron-prod:/nail/tron/* example-cluster/\ngit checkout example"
},
{
"path": "contrib/sync_namespaces_jobs.py",
"chars": 2393,
"preview": "#!/usr/bin/env python\n\"\"\" This script is for load testing of Tron\n\nHistorically, Tronview and Tronweb were (are) slow. T"
},
{
"path": "debian/changelog",
"chars": 114506,
"preview": "tron (3.10.0) jammy; urgency=medium\n\n * 3.10.0 tagged with 'make release'\n Commit: Merge pull request #1096 from Yel"
},
{
"path": "debian/compat",
"chars": 3,
"preview": "10\n"
},
{
"path": "debian/control",
"chars": 676,
"preview": "Source: tron\nSection: admin\nPriority: optional\nMaintainer: Daniel Nephin <dnephin@yelp.com>\nBuild-Depends: debhelper (>="
},
{
"path": "debian/copyright",
"chars": 837,
"preview": "This package was debianized by Steve Johnson <sjohnson@yelp.com>\n on Sat, 26 Nov 2011 15:13:00 -0400.\n\nIt was downloaded"
},
{
"path": "debian/docs",
"chars": 22,
"preview": "LICENSE.txt\nREADME.md\n"
},
{
"path": "debian/install",
"chars": 56,
"preview": "tron/logging.conf var/lib/tron\ntronweb/ opt/venvs/tron/\n"
},
{
"path": "debian/pycompat",
"chars": 2,
"preview": "2\n"
},
{
"path": "debian/pyversions",
"chars": 8,
"preview": "2.5-2.6\n"
},
{
"path": "debian/rules",
"chars": 919,
"preview": "#!/usr/bin/make -f\n# -*- makefile -*-\n\nDH_VERBOSE := 1\n\n%:\n\tdh $@ --with python-virtualenv\n\n# do not call `make clean` a"
},
{
"path": "debian/tron.conffiles",
"chars": 27,
"preview": "/var/lib/tron/logging.conf\n"
},
{
"path": "debian/tron.default",
"chars": 591,
"preview": "# Defaults for tron initscript\n# sourced by /etc/init.d/tron\n# installed at /etc/default/tron by the maintainer scripts\n"
},
{
"path": "debian/tron.dirs",
"chars": 28,
"preview": "var/lib/tron/\nvar/log/tron/\n"
},
{
"path": "debian/tron.example",
"chars": 19,
"preview": "sample_config.yaml\n"
},
{
"path": "debian/tron.links",
"chars": 507,
"preview": "opt/venvs/tron/bin/check_tron_jobs usr/bin/check_tron_jobs.py\nopt/venvs/tron/bin/tronctl usr/bin/tronctl\nopt/venvs/tron/"
},
{
"path": "debian/tron.manpages",
"chars": 103,
"preview": "docs/source/man/tronctl.1\ndocs/source/man/trond.8\ndocs/source/man/tronview.1\ndocs/source/man/tronfig.1\n"
},
{
"path": "debian/tron.postinst",
"chars": 72,
"preview": "#!/bin/sh -e\n#\n# Post-installation script for tron\n\n#DEBHELPER#\n\nexit 0\n"
},
{
"path": "debian/tron.service",
"chars": 1005,
"preview": "[Unit]\nDescription=trond\nAfter=network.target\n# Attempt restarts indefinitely (If omitted, systemd attempts max 5x withi"
},
{
"path": "debian/tron.upstart",
"chars": 514,
"preview": "description \"trond\"\n\nstart on filesystem and (started networking)\nstop on shutdown\n\nrespawn\nkill timeout 20\n\nscript\n se"
},
{
"path": "debian/watch",
"chars": 281,
"preview": "# Example watch control file for uscan\n# Rename this file to \"watch\" and then you can run the \"uscan\" command\n# to check"
},
{
"path": "dev/config/MASTER.yaml",
"chars": 1592,
"preview": "# Please visit y/tron-development for a guide on how to setup Tron for local development\nstate_persistence:\n name: \"tro"
},
{
"path": "dev/config/_manifest.yaml",
"chars": 27,
"preview": "MASTER: config/MASTER.yaml\n"
},
{
"path": "dev/logging.conf",
"chars": 1396,
"preview": "[loggers]\nkeys=root, twisted, tron, tron.serialize.runstate.statemanager, tron.api.www.access, task_processing, tron.mes"
},
{
"path": "docs/source/_static/nature.css",
"chars": 4142,
"preview": "/*\n * nature.css_t\n * ~~~~~~~~~~~~\n *\n * Sphinx stylesheet -- nature theme.\n *\n * :copyright: Copyright 2007-2011 by the"
},
{
"path": "docs/source/command_context.rst",
"chars": 5263,
"preview": "\n.. _built_in_cc:\n\nBuilt-In Command Context Variables\n==================================\n\nTron includes some built in co"
},
{
"path": "docs/source/conf.py",
"chars": 8191,
"preview": "#\n# Tron documentation build configuration file, created by\n# sphinx-quickstart on Mon Nov 7 18:05:54 2011.\n#\n# This fi"
},
{
"path": "docs/source/config.rst",
"chars": 8400,
"preview": "Configuration\n=============\n\n.. _config_syntax:\n\nSyntax\n------\n\nThe Tron configuration file uses YAML syntax. The recomm"
},
{
"path": "docs/source/developing.rst",
"chars": 1671,
"preview": ".. _developing:\n\nContributing to Tron\n====================\n\nTron is an open source project and welcomes contributions fr"
},
{
"path": "docs/source/generated/modules.rst",
"chars": 49,
"preview": "tron\n====\n\n.. toctree::\n :maxdepth: 4\n\n tron\n"
},
{
"path": "docs/source/generated/tron.actioncommand.rst",
"chars": 142,
"preview": "tron.actioncommand module\n=========================\n\n.. automodule:: tron.actioncommand\n :members:\n :undoc-members:\n"
},
{
"path": "docs/source/generated/tron.api.adapter.rst",
"chars": 136,
"preview": "tron.api.adapter module\n=======================\n\n.. automodule:: tron.api.adapter\n :members:\n :undoc-members:\n :sh"
},
{
"path": "docs/source/generated/tron.api.async_resource.rst",
"chars": 159,
"preview": "tron.api.async\\_resource module\n===============================\n\n.. automodule:: tron.api.async_resource\n :members:\n "
},
{
"path": "docs/source/generated/tron.api.auth.rst",
"chars": 127,
"preview": "tron.api.auth module\n====================\n\n.. automodule:: tron.api.auth\n :members:\n :undoc-members:\n :show-inheri"
},
{
"path": "docs/source/generated/tron.api.controller.rst",
"chars": 145,
"preview": "tron.api.controller module\n==========================\n\n.. automodule:: tron.api.controller\n :members:\n :undoc-member"
},
{
"path": "docs/source/generated/tron.api.requestargs.rst",
"chars": 148,
"preview": "tron.api.requestargs module\n===========================\n\n.. automodule:: tron.api.requestargs\n :members:\n :undoc-mem"
},
{
"path": "docs/source/generated/tron.api.resource.rst",
"chars": 139,
"preview": "tron.api.resource module\n========================\n\n.. automodule:: tron.api.resource\n :members:\n :undoc-members:\n "
},
{
"path": "docs/source/generated/tron.api.rst",
"chars": 333,
"preview": "tron.api package\n================\n\nSubmodules\n----------\n\n.. toctree::\n :maxdepth: 4\n\n tron.api.adapter\n tron.api."
},
{
"path": "docs/source/generated/tron.command_context.rst",
"chars": 150,
"preview": "tron.command\\_context module\n============================\n\n.. automodule:: tron.command_context\n :members:\n :undoc-m"
},
{
"path": "docs/source/generated/tron.commands.authentication.rst",
"chars": 172,
"preview": "tron.commands.authentication module\n===================================\n\n.. automodule:: tron.commands.authentication\n "
},
{
"path": "docs/source/generated/tron.commands.backfill.rst",
"chars": 154,
"preview": "tron.commands.backfill module\n=============================\n\n.. automodule:: tron.commands.backfill\n :members:\n :und"
},
{
"path": "docs/source/generated/tron.commands.client.rst",
"chars": 148,
"preview": "tron.commands.client module\n===========================\n\n.. automodule:: tron.commands.client\n :members:\n :undoc-mem"
},
{
"path": "docs/source/generated/tron.commands.cmd_utils.rst",
"chars": 159,
"preview": "tron.commands.cmd\\_utils module\n===============================\n\n.. automodule:: tron.commands.cmd_utils\n :members:\n "
},
{
"path": "docs/source/generated/tron.commands.display.rst",
"chars": 151,
"preview": "tron.commands.display module\n============================\n\n.. automodule:: tron.commands.display\n :members:\n :undoc-"
},
{
"path": "docs/source/generated/tron.commands.retry.rst",
"chars": 145,
"preview": "tron.commands.retry module\n==========================\n\n.. automodule:: tron.commands.retry\n :members:\n :undoc-member"
},
{
"path": "docs/source/generated/tron.commands.rst",
"chars": 373,
"preview": "tron.commands package\n=====================\n\nSubmodules\n----------\n\n.. toctree::\n :maxdepth: 4\n\n tron.commands.authe"
},
{
"path": "docs/source/generated/tron.config.config_parse.rst",
"chars": 162,
"preview": "tron.config.config\\_parse module\n================================\n\n.. automodule:: tron.config.config_parse\n :members:"
},
{
"path": "docs/source/generated/tron.config.config_utils.rst",
"chars": 162,
"preview": "tron.config.config\\_utils module\n================================\n\n.. automodule:: tron.config.config_utils\n :members:"
},
{
"path": "docs/source/generated/tron.config.manager.rst",
"chars": 145,
"preview": "tron.config.manager module\n==========================\n\n.. automodule:: tron.config.manager\n :members:\n :undoc-member"
},
{
"path": "docs/source/generated/tron.config.rst",
"chars": 370,
"preview": "tron.config package\n===================\n\nSubmodules\n----------\n\n.. toctree::\n :maxdepth: 4\n\n tron.config.config_pars"
},
{
"path": "docs/source/generated/tron.config.schedule_parse.rst",
"chars": 168,
"preview": "tron.config.schedule\\_parse module\n==================================\n\n.. automodule:: tron.config.schedule_parse\n :me"
},
{
"path": "docs/source/generated/tron.config.schema.rst",
"chars": 142,
"preview": "tron.config.schema module\n=========================\n\n.. automodule:: tron.config.schema\n :members:\n :undoc-members:\n"
},
{
"path": "docs/source/generated/tron.config.static_config.rst",
"chars": 165,
"preview": "tron.config.static\\_config module\n=================================\n\n.. automodule:: tron.config.static_config\n :membe"
},
{
"path": "docs/source/generated/tron.core.action.rst",
"chars": 136,
"preview": "tron.core.action module\n=======================\n\n.. automodule:: tron.core.action\n :members:\n :undoc-members:\n :sh"
},
{
"path": "docs/source/generated/tron.core.actiongraph.rst",
"chars": 151,
"preview": "tron.core.actiongraph module\n============================\n\n.. automodule:: tron.core.actiongraph\n :members:\n :undoc-"
},
{
"path": "docs/source/generated/tron.core.actionrun.rst",
"chars": 145,
"preview": "tron.core.actionrun module\n==========================\n\n.. automodule:: tron.core.actionrun\n :members:\n :undoc-member"
},
{
"path": "docs/source/generated/tron.core.job.rst",
"chars": 127,
"preview": "tron.core.job module\n====================\n\n.. automodule:: tron.core.job\n :members:\n :undoc-members:\n :show-inheri"
},
{
"path": "docs/source/generated/tron.core.job_collection.rst",
"chars": 162,
"preview": "tron.core.job\\_collection module\n================================\n\n.. automodule:: tron.core.job_collection\n :members:"
},
{
"path": "docs/source/generated/tron.core.job_scheduler.rst",
"chars": 159,
"preview": "tron.core.job\\_scheduler module\n===============================\n\n.. automodule:: tron.core.job_scheduler\n :members:\n "
},
{
"path": "docs/source/generated/tron.core.jobgraph.rst",
"chars": 142,
"preview": "tron.core.jobgraph module\n=========================\n\n.. automodule:: tron.core.jobgraph\n :members:\n :undoc-members:\n"
},
{
"path": "docs/source/generated/tron.core.jobrun.rst",
"chars": 136,
"preview": "tron.core.jobrun module\n=======================\n\n.. automodule:: tron.core.jobrun\n :members:\n :undoc-members:\n :sh"
},
{
"path": "docs/source/generated/tron.core.recovery.rst",
"chars": 142,
"preview": "tron.core.recovery module\n=========================\n\n.. automodule:: tron.core.recovery\n :members:\n :undoc-members:\n"
},
{
"path": "docs/source/generated/tron.core.rst",
"chars": 408,
"preview": "tron.core package\n=================\n\nSubmodules\n----------\n\n.. toctree::\n :maxdepth: 4\n\n tron.core.action\n tron.co"
},
{
"path": "docs/source/generated/tron.eventbus.rst",
"chars": 127,
"preview": "tron.eventbus module\n====================\n\n.. automodule:: tron.eventbus\n :members:\n :undoc-members:\n :show-inheri"
},
{
"path": "docs/source/generated/tron.kubernetes.rst",
"chars": 133,
"preview": "tron.kubernetes module\n======================\n\n.. automodule:: tron.kubernetes\n :members:\n :undoc-members:\n :show-"
},
{
"path": "docs/source/generated/tron.manhole.rst",
"chars": 124,
"preview": "tron.manhole module\n===================\n\n.. automodule:: tron.manhole\n :members:\n :undoc-members:\n :show-inheritan"
},
{
"path": "docs/source/generated/tron.mcp.rst",
"chars": 112,
"preview": "tron.mcp module\n===============\n\n.. automodule:: tron.mcp\n :members:\n :undoc-members:\n :show-inheritance:\n"
},
{
"path": "docs/source/generated/tron.mesos.rst",
"chars": 118,
"preview": "tron.mesos module\n=================\n\n.. automodule:: tron.mesos\n :members:\n :undoc-members:\n :show-inheritance:\n"
},
{
"path": "docs/source/generated/tron.metrics.rst",
"chars": 124,
"preview": "tron.metrics module\n===================\n\n.. automodule:: tron.metrics\n :members:\n :undoc-members:\n :show-inheritan"
},
{
"path": "docs/source/generated/tron.node.rst",
"chars": 115,
"preview": "tron.node module\n================\n\n.. automodule:: tron.node\n :members:\n :undoc-members:\n :show-inheritance:\n"
},
{
"path": "docs/source/generated/tron.prom_metrics.rst",
"chars": 141,
"preview": "tron.prom\\_metrics module\n=========================\n\n.. automodule:: tron.prom_metrics\n :members:\n :undoc-members:\n "
},
{
"path": "docs/source/generated/tron.rst",
"chars": 570,
"preview": "tron package\n============\n\nSubpackages\n-----------\n\n.. toctree::\n :maxdepth: 4\n\n tron.api\n tron.commands\n tron.c"
},
{
"path": "docs/source/generated/tron.scheduler.rst",
"chars": 130,
"preview": "tron.scheduler module\n=====================\n\n.. automodule:: tron.scheduler\n :members:\n :undoc-members:\n :show-inh"
},
{
"path": "docs/source/generated/tron.serialize.filehandler.rst",
"chars": 166,
"preview": "tron.serialize.filehandler module\n=================================\n\n.. automodule:: tron.serialize.filehandler\n :memb"
},
{
"path": "docs/source/generated/tron.serialize.rst",
"chars": 332,
"preview": "tron.serialize package\n======================\n\nSubpackages\n-----------\n\n.. toctree::\n :maxdepth: 4\n\n tron.serialize."
},
{
"path": "docs/source/generated/tron.serialize.runstate.dynamodb_state_store.rst",
"chars": 224,
"preview": "tron.serialize.runstate.dynamodb\\_state\\_store module\n=====================================================\n\n.. automodu"
},
{
"path": "docs/source/generated/tron.serialize.runstate.rst",
"chars": 410,
"preview": "tron.serialize.runstate package\n===============================\n\nSubmodules\n----------\n\n.. toctree::\n :maxdepth: 4\n\n "
},
{
"path": "docs/source/generated/tron.serialize.runstate.shelvestore.rst",
"chars": 193,
"preview": "tron.serialize.runstate.shelvestore module\n==========================================\n\n.. automodule:: tron.serialize.ru"
},
{
"path": "docs/source/generated/tron.serialize.runstate.statemanager.rst",
"chars": 196,
"preview": "tron.serialize.runstate.statemanager module\n===========================================\n\n.. automodule:: tron.serialize."
},
{
"path": "docs/source/generated/tron.serialize.runstate.yamlstore.rst",
"chars": 187,
"preview": "tron.serialize.runstate.yamlstore module\n========================================\n\n.. automodule:: tron.serialize.runsta"
},
{
"path": "docs/source/generated/tron.ssh.rst",
"chars": 112,
"preview": "tron.ssh module\n===============\n\n.. automodule:: tron.ssh\n :members:\n :undoc-members:\n :show-inheritance:\n"
},
{
"path": "docs/source/generated/tron.trondaemon.rst",
"chars": 133,
"preview": "tron.trondaemon module\n======================\n\n.. automodule:: tron.trondaemon\n :members:\n :undoc-members:\n :show-"
},
{
"path": "docs/source/generated/tron.utils.collections.rst",
"chars": 154,
"preview": "tron.utils.collections module\n=============================\n\n.. automodule:: tron.utils.collections\n :members:\n :und"
},
{
"path": "docs/source/generated/tron.utils.crontab.rst",
"chars": 142,
"preview": "tron.utils.crontab module\n=========================\n\n.. automodule:: tron.utils.crontab\n :members:\n :undoc-members:\n"
},
{
"path": "docs/source/generated/tron.utils.exitcode.rst",
"chars": 145,
"preview": "tron.utils.exitcode module\n==========================\n\n.. automodule:: tron.utils.exitcode\n :members:\n :undoc-member"
},
{
"path": "docs/source/generated/tron.utils.logreader.rst",
"chars": 148,
"preview": "tron.utils.logreader module\n===========================\n\n.. automodule:: tron.utils.logreader\n :members:\n :undoc-mem"
},
{
"path": "docs/source/generated/tron.utils.observer.rst",
"chars": 145,
"preview": "tron.utils.observer module\n==========================\n\n.. automodule:: tron.utils.observer\n :members:\n :undoc-member"
},
{
"path": "docs/source/generated/tron.utils.persistable.rst",
"chars": 154,
"preview": "tron.utils.persistable module\n=============================\n\n.. automodule:: tron.utils.persistable\n :members:\n :und"
},
{
"path": "docs/source/generated/tron.utils.proxy.rst",
"chars": 136,
"preview": "tron.utils.proxy module\n=======================\n\n.. automodule:: tron.utils.proxy\n :members:\n :undoc-members:\n :sh"
},
{
"path": "docs/source/generated/tron.utils.queue.rst",
"chars": 136,
"preview": "tron.utils.queue module\n=======================\n\n.. automodule:: tron.utils.queue\n :members:\n :undoc-members:\n :sh"
},
{
"path": "docs/source/generated/tron.utils.rst",
"chars": 489,
"preview": "tron.utils package\n==================\n\nSubmodules\n----------\n\n.. toctree::\n :maxdepth: 4\n\n tron.utils.collections\n "
},
{
"path": "docs/source/generated/tron.utils.state.rst",
"chars": 136,
"preview": "tron.utils.state module\n=======================\n\n.. automodule:: tron.utils.state\n :members:\n :undoc-members:\n :sh"
},
{
"path": "docs/source/generated/tron.utils.timeutils.rst",
"chars": 148,
"preview": "tron.utils.timeutils module\n===========================\n\n.. automodule:: tron.utils.timeutils\n :members:\n :undoc-mem"
},
{
"path": "docs/source/generated/tron.utils.trontimespec.rst",
"chars": 157,
"preview": "tron.utils.trontimespec module\n==============================\n\n.. automodule:: tron.utils.trontimespec\n :members:\n :"
},
{
"path": "docs/source/generated/tron.utils.twistedutils.rst",
"chars": 157,
"preview": "tron.utils.twistedutils module\n==============================\n\n.. automodule:: tron.utils.twistedutils\n :members:\n :"
},
{
"path": "docs/source/generated/tron.yaml.rst",
"chars": 115,
"preview": "tron.yaml module\n================\n\n.. automodule:: tron.yaml\n :members:\n :undoc-members:\n :show-inheritance:\n"
},
{
"path": "docs/source/index.rst",
"chars": 757,
"preview": "Tron\n====\n\nTron is a centralized system for managing periodic batch processes\nacross a cluster. If this is your first ti"
},
{
"path": "docs/source/jobs.rst",
"chars": 15937,
"preview": "Jobs\n====\n\nA job consists of a name, a node/node pool, a list of actions, a schedule, and\nan optional cleanup action. Th"
},
{
"path": "docs/source/man/tronctl.1",
"chars": 4295,
"preview": ".TH \"TRONCTL\" \"1\" \"April 24, 2013\" \"0.6\" \"Tron\"\n.SH NAME\ntronctl \\- control Tron jobs and services\n.\n.nr rst2man-indent-"
},
{
"path": "docs/source/man/trond.8",
"chars": 3238,
"preview": ".TH \"TROND\" \"8\" \"April 24, 2013\" \"0.6\" \"Tron\"\n.SH NAME\ntrond \\- trond documentation\n.\n.nr rst2man-indent-level 0\n.\n.de1 "
},
{
"path": "docs/source/man/tronfig.1",
"chars": 1998,
"preview": ".TH \"TRONFIG\" \"1\" \"April 24, 2013\" \"0.6\" \"Tron\"\n.SH NAME\ntronfig \\- tronfig documentation\n.\n.nr rst2man-indent-level 0\n."
},
{
"path": "docs/source/man/tronview.1",
"chars": 2726,
"preview": ".TH \"TRONVIEW\" \"1\" \"April 24, 2013\" \"0.6\" \"Tron\"\n.SH NAME\ntronview \\- tronview documentation\n.\n.nr rst2man-indent-level "
},
{
"path": "docs/source/man_tronctl.rst",
"chars": 4007,
"preview": ".. _tronctl:\n\ntronctl\n=======\n\nSynopsis\n--------\n\n``tronctl [--server <host:port>] [--verbose] <command> <job_name | job"
},
{
"path": "docs/source/man_trond.rst",
"chars": 2190,
"preview": ".. _trond:\n\ntrond\n=====\n\nSynopsis\n--------\n\n``trond [--working-dir=<working dir>] [--verbose] [--debug]``\n\nDescription\n-"
},
{
"path": "docs/source/man_tronfig.rst",
"chars": 1092,
"preview": ".. _tronfig:\n\ntronfig\n=======\n\nSynopsis\n--------\n\n``tronfig [--server server_name ] [--verbose | -v] [<namespace>] [-p] "
},
{
"path": "docs/source/man_tronview.rst",
"chars": 1531,
"preview": ".. _tronview:\n\ntronview\n========\n\nSynopsis\n--------\n\n``tronview [-n <numshown>] [--server <server_name>] [--verbose] [<j"
},
{
"path": "docs/source/overview.rst",
"chars": 3282,
"preview": "Overview\n========\n\nBatch process scheduling on a single UNIX machines has\nhistorically been managed by :command:`cron` a"
},
{
"path": "docs/source/sample_config.yaml",
"chars": 1163,
"preview": "# optional and settable from the command line\nworking_dir: './working'\n\n# optional\nssh_options:\n agent: true # default "
},
{
"path": "docs/source/tools.rst",
"chars": 131,
"preview": "Man Pages\n=========\n\n.. toctree::\n :maxdepth: 2\n\n man_tronctl.rst\n man_trond.rst\n man_tronfig.rst\n man_tr"
},
{
"path": "docs/source/tron.yaml",
"chars": 206,
"preview": "ssh_options:\n agent: true\n\nnodes:\n - name: node0\n hostname: 'localhost'\n\njobs:\n \"uptime_job\":\n node: node0\n "
},
{
"path": "docs/source/tronweb.rst",
"chars": 102,
"preview": ".. _tronweb:\n\ntronweb\n========\n\ntronweb is the web-based UI for tron.\n\nSee http://localhost:8089/web/\n"
},
{
"path": "docs/source/tutorial.rst",
"chars": 4060,
"preview": "Tutorial\n========\n\nTo install Tron you will need:\n\n* A copy of the most recent Tron release from either\n `github <http:"
},
{
"path": "docs/source/whats-new.rst",
"chars": 92,
"preview": "What's New\n==========\n\nSee the `CHANGELOG <https://github.com/Yelp/Tron/releases/latest>`_.\n"
},
{
"path": "itest.sh",
"chars": 1357,
"preview": "#!/bin/bash\n\nset -euxo pipefail\n\nexport DEBIAN_FRONTEND=noninteractive\n\napt-get update\napt-get install -y software-prope"
},
{
"path": "mypy.ini",
"chars": 625,
"preview": "[mypy]\npython_version = 3.10\n# TODO: we'd like to be as strict as we are internally, but we need to fully type Tron firs"
},
{
"path": "osx-bdb.sh",
"chars": 126,
"preview": "#!/bin/bash\n\nexport BERKELEYDB_DIR=$(brew --prefix berkeley-db)\nexport YES_I_HAVE_THE_RIGHT_TO_USE_THIS_BERKELEY_DB_VERS"
},
{
"path": "package.json",
"chars": 773,
"preview": "{\n \"private\": true,\n \"homepage\": \"./\",\n \"dependencies\": {},\n \"browserslist\": {\n \"production\": [\n "
},
{
"path": "pyproject.toml",
"chars": 58,
"preview": "[tool.black]\nline-length = 120\ntarget_version = ['py310']\n"
},
{
"path": "requirements-dev-minimal.txt",
"chars": 252,
"preview": "asynctest\nbotocore-stubs\ndebugpy\nflake8\nmoto\nmypy\npre-commit\npytest\npytest-asyncio\nrequirements-tools\ntypes-boto3\ntypes-"
},
{
"path": "requirements-dev.txt",
"chars": 785,
"preview": "asynctest==0.12.0\nboto3-stubs==1.35.63\nbotocore-stubs==1.38.19\ncfgv==2.0.1\ndebugpy==1.8.1\ndistlib==0.3.6\nfilelock==3.4.1"
},
{
"path": "requirements-docs.txt",
"chars": 101,
"preview": "Jinja2==3.1.2\nmarkupsafe==2.1.1\nmock==3.0.5\nPygments==2.13.0\nSphinx==6.1.3\nSphinx-PyPI-upload==0.2.1\n"
},
{
"path": "requirements-minimal.txt",
"chars": 854,
"preview": "addict # not sure why check-requirements is not picking this up from task_processing[mesos_executor]\nargcomplete\nboto3\n"
},
{
"path": "requirements.txt",
"chars": 1331,
"preview": "addict==2.2.1\nargcomplete==1.9.5\nasttokens==2.2.1\nattrs==19.3.0\nAutomat==20.2.0\nbackcall==0.1.0\nboto3==1.34.80\nbotocore="
},
{
"path": "setup.cfg",
"chars": 117,
"preview": "[build_docs]\nsource-dir = docs/\nbuild-dir = docs/_build\nall_files = 1\n\n[upload_docs]\nupload_dir = docs/_build/html\n"
},
{
"path": "setup.py",
"chars": 1467,
"preview": "try:\n from setuptools import setup, find_packages\n\n assert setup\nexcept ImportError:\n from distutils.core impor"
},
{
"path": "testfiles/MASTER.yaml",
"chars": 800,
"preview": "eventbus_enabled: true\n\nstate_persistence:\n name: \"/nail/tron/tron_state\"\n store_type: \"shelve\"\n buffer_size: 10\n\nssh"
},
{
"path": "testifycompat/__init__.py",
"chars": 431,
"preview": "from unittest import TestCase # noqa: F401\n\nfrom testifycompat.assertions import * # noqa: F401, F403\nfrom testifycomp"
},
{
"path": "testifycompat/assertions.py",
"chars": 2414,
"preview": "\"\"\"Compatiblity functions for py.test to migrate code from testify.\n\nThis is not a complete list, but should hopefully c"
},
{
"path": "testifycompat/bin/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "testifycompat/bin/migrate.py",
"chars": 1753,
"preview": "#!/usr/bin/env python\n\"\"\"\n\n.. warning::\n\n This script is still very experimental. Use at your own risk. It will\n b"
},
{
"path": "testifycompat/fixtures.py",
"chars": 1350,
"preview": "\"\"\"\nCompatibility fixtures for migrating code from testify to py.test\n\n.. note::\n\n ``class_`` fixtures must be applie"
},
{
"path": "tests/__init__.py",
"chars": 88,
"preview": "from twisted.python import log\n\nobserver = log.PythonLoggingObserver()\nobserver.start()\n"
},
{
"path": "tests/actioncommand_test.py",
"chars": 7180,
"preview": "import shlex\nfrom unittest import mock\n\nfrom testifycompat import assert_equal\nfrom testifycompat import assert_not_equa"
},
{
"path": "tests/api/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "tests/api/adapter_test.py",
"chars": 8248,
"preview": "import shutil\nimport tempfile\nfrom unittest import mock\n\nfrom testifycompat import assert_equal\nfrom testifycompat impor"
},
{
"path": "tests/api/auth_test.py",
"chars": 3129,
"preview": "from unittest.mock import MagicMock\nfrom unittest.mock import patch\n\nimport pytest\nfrom twisted.web.server import Reques"
},
{
"path": "tests/api/controller_test.py",
"chars": 12884,
"preview": "from unittest import mock\n\nimport pytest\n\nfrom tron import mcp\nfrom tron.api import controller\nfrom tron.api.controller "
},
{
"path": "tests/api/requestargs_test.py",
"chars": 2238,
"preview": "import datetime\nfrom unittest.mock import MagicMock\n\nfrom testifycompat import assert_equal\nfrom testifycompat import ru"
},
{
"path": "tests/api/resource_test.py",
"chars": 13647,
"preview": "\"\"\"\nTest cases for the web services interface to tron\n\"\"\"\nfrom unittest import mock\nfrom unittest.mock import MagicMock\n"
},
{
"path": "tests/assertions.py",
"chars": 1303,
"preview": "\"\"\"\n Assertions for testify.\n\"\"\"\nfrom testifycompat import assert_in\nfrom testifycompat import assert_not_reached\n\n\ndef "
},
{
"path": "tests/bin/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "tests/bin/action_runner_test.py",
"chars": 7286,
"preview": "import tempfile\nfrom unittest import mock\n\nimport pytest\n\nfrom testifycompat import assert_equal\nfrom testifycompat impo"
},
{
"path": "tests/bin/action_status_test.py",
"chars": 1772,
"preview": "import signal\nimport tempfile\nfrom unittest import mock\n\nfrom testifycompat import setup_teardown\nfrom testifycompat imp"
},
{
"path": "tests/bin/check_tron_jobs_test.py",
"chars": 59612,
"preview": "import time\nfrom unittest import mock\nfrom unittest.mock import patch\nfrom unittest.mock import PropertyMock\n\nimport pyt"
},
{
"path": "tests/bin/get_tron_metrics_test.py",
"chars": 4222,
"preview": "import subprocess\nfrom unittest import mock\n\nimport pytest\n\nfrom tron.bin import get_tron_metrics\n\n\ndef test_send_data_m"
},
{
"path": "tests/bin/recover_batch_test.py",
"chars": 4467,
"preview": "import tempfile\nfrom queue import Queue\nfrom unittest import mock\n\nimport pytest\n\nfrom tron.bin import recover_batch\nfro"
},
{
"path": "tests/command_context_test.py",
"chars": 7629,
"preview": "import datetime\nfrom unittest import mock\n\nfrom testifycompat import assert_equal\nfrom testifycompat import assert_raise"
},
{
"path": "tests/commands/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "tests/commands/backfill_test.py",
"chars": 6026,
"preview": "import datetime\nfrom unittest import mock\n\nimport pytest\n\nfrom tron.commands import backfill\nfrom tron.commands import c"
},
{
"path": "tests/commands/client_test.py",
"chars": 9410,
"preview": "from unittest import mock\nfrom urllib.error import HTTPError\nfrom urllib.error import URLError\n\nfrom testifycompat impor"
},
{
"path": "tests/commands/cmd_utils_test.py",
"chars": 4725,
"preview": "import argparse\nfrom unittest import mock\n\nfrom testifycompat import assert_equal\nfrom testifycompat import assert_in\nfr"
},
{
"path": "tests/commands/display_test.py",
"chars": 5977,
"preview": "from unittest import mock\n\nfrom testifycompat import setup\nfrom testifycompat import setup_teardown\nfrom testifycompat i"
},
{
"path": "tests/commands/retry_test.py",
"chars": 8685,
"preview": "import random\nfrom unittest import mock\n\nimport pytest\n\nfrom tron.commands import client\nfrom tron.commands import retry"
},
{
"path": "tests/config/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "tests/config/config_parse_test.py",
"chars": 63994,
"preview": "import datetime\nimport os\nimport shutil\nimport tempfile\nfrom unittest import mock\n\nimport pytest\nimport pytz\n\nfrom testi"
},
{
"path": "tests/config/config_utils_test.py",
"chars": 6658,
"preview": "import datetime\nfrom unittest import mock\n\nfrom testifycompat import assert_equal\nfrom testifycompat import assert_in\nfr"
},
{
"path": "tests/config/manager_test.py",
"chars": 8952,
"preview": "import os\nimport shutil\nimport tempfile\nfrom unittest import mock\n\nfrom testifycompat import assert_equal\nfrom testifyco"
},
{
"path": "tests/config/schedule_parse_test.py",
"chars": 4813,
"preview": "import datetime\nfrom unittest import mock\n\nfrom testifycompat import assert_equal\nfrom testifycompat import assert_raise"
},
{
"path": "tests/core/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "tests/core/action_test.py",
"chars": 9542,
"preview": "import pytest\n\nfrom tron.config.schema import ConfigAction\nfrom tron.config.schema import ConfigConstraint\nfrom tron.con"
},
{
"path": "tests/core/actiongraph_test.py",
"chars": 2742,
"preview": "from unittest import mock\n\nfrom testifycompat import assert_equal\nfrom testifycompat import assert_raises\nfrom testifyco"
},
{
"path": "tests/core/actionrun_test.py",
"chars": 83508,
"preview": "import datetime\nimport shutil\nimport tempfile\nfrom unittest import mock\nfrom unittest.mock import MagicMock\n\nimport pyte"
},
{
"path": "tests/core/job_collection_test.py",
"chars": 3879,
"preview": "from unittest import mock\n\nfrom testifycompat import setup\nfrom testifycompat import TestCase\nfrom tests.testingutils im"
},
{
"path": "tests/core/job_scheduler_test.py",
"chars": 12203,
"preview": "import datetime\nfrom unittest import mock\n\nfrom testifycompat import assert_equal\nfrom testifycompat import setup\nfrom t"
},
{
"path": "tests/core/job_test.py",
"chars": 15701,
"preview": "import collections\nimport datetime\nfrom unittest import mock\nfrom unittest.mock import MagicMock\n\nimport pytest\n\nfrom te"
},
{
"path": "tests/core/jobgraph_test.py",
"chars": 5425,
"preview": "from unittest import mock\n\nimport pytest\n\nfrom tron.config.schema import ConfigAction\nfrom tron.config.schema import Con"
},
{
"path": "tests/core/jobrun_test.py",
"chars": 39683,
"preview": "import datetime\nimport json\nfrom unittest import mock\nfrom unittest.mock import MagicMock\n\nimport pytest\nimport pytz\n\nfr"
},
{
"path": "tests/core/recovery_test.py",
"chars": 5399,
"preview": "from unittest import mock\nfrom unittest.mock import Mock\n\nfrom testifycompat import setup\nfrom testifycompat import Test"
},
{
"path": "tests/data/logging.conf",
"chars": 484,
"preview": "[loggers]\nkeys=root, twisted, tron\n\n[handlers]\nkeys=fileHandler\n\n[formatters]\nkeys=defaultFormatter\n\n[logger_root]\nlevel"
},
{
"path": "tests/data/test_config.yaml",
"chars": 4701,
"preview": "# This test config is intended to cover most common configuration cases\n\nssh_options:\n agent: true\n\nstate_persistence"
},
{
"path": "tests/eventbus_test.py",
"chars": 8868,
"preview": "import os\nimport tempfile\nfrom collections import defaultdict\nfrom unittest import mock\n\nfrom testifycompat import asser"
},
{
"path": "tests/kubernetes_test.py",
"chars": 29290,
"preview": "from typing import Any\nfrom unittest import mock\n\nimport pytest\nfrom task_processing.interfaces.event import Event\nfrom "
},
{
"path": "tests/mcp_reconfigure_test.py",
"chars": 12008,
"preview": "\"\"\"Tests for reconfiguring mcp.\"\"\"\nimport os\nimport tempfile\nimport time\n\nimport pytest\n\nfrom testifycompat import asser"
},
{
"path": "tests/mcp_test.py",
"chars": 6316,
"preview": "import shutil\nimport tempfile\nimport time\nfrom unittest import mock\n\nimport pytest\n\nfrom testifycompat import assert_equ"
}
]
// ... and 147 more files (download for full content)
About this extraction
This page contains the full source code of the Yelp/Tron GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 347 files (2.5 MB), approximately 668.0k tokens, and a symbol index with 3312 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.