def main(): """ This entry point script expects certain env variables * COMMAND_NAME (optional, defaults to qontract-reconcile) an entry point as defined in setup.py must be a click.Command * INTEGRATION_NAME used as name for the subcommand for command if present as a subcommand on the click command * INTEGRATION_EXTRA_ARGS (optional) space separated list of arguments that will be passed to the command or subcommand * CONFIG path to the config toml file * LOG_FILE path for the logfile to write to * DRY_RUN (optional) this is not a boolean but must contain the actual dry-run flag value, so --dry-run or --no-dry-run * RUN_ONCE (optional) if 'true', execute the integration once and exit otherwise run the integration in a loop controlled by SLEEP_DURATION_SECS and SLEEP_ON_ERROR * SLEEP_DURATION_SECS (default 600) amount of seconds to sleep between successful integration runs * SLEEP_ON_ERROR (default 10) amount of seconds to sleep before another integration run is started Based on those variables, the following command will be executed $COMMAND --config $CONFIG $DRY_RUN $INTEGRATION_NAME \ $INTEGRATION_EXTRA_ARGS """ start_http_server(9090) command = build_entry_point_func(COMMAND_NAME) while True: args = build_entry_point_args(command, CONFIG, DRY_RUN, INTEGRATION_NAME, INTEGRATION_EXTRA_ARGS) sleep = SLEEP_DURATION_SECS start_time = time.monotonic() # Running the integration via Click, so we don't have to replicate # the CLI logic here try: with command.make_context(info_name=COMMAND_NAME, args=args) \ as ctx: ctx.ensure_object(dict) ctx.obj['extra_labels'] = extra_labels command.invoke(ctx) return_code = 0 # This is for when the integration explicitly # calls sys.exit(N) except SystemExit as exc_obj: return_code = int(exc_obj.code) # We have to be generic since we don't know what can happen # in the integrations, but we want to continue the loop anyway except Exception: sleep = SLEEP_ON_ERROR LOG.exception(f"Error running {COMMAND_NAME}") return_code = ExitCodes.ERROR time_spent = time.monotonic() - start_time run_time.labels(integration=INTEGRATION_NAME, shards=SHARDS, shard_id=SHARD_ID, **extra_labels).set(time_spent) run_status.labels(integration=INTEGRATION_NAME, shards=SHARDS, shard_id=SHARD_ID, **extra_labels).set(return_code) if RUN_ONCE: sys.exit(return_code) time.sleep(int(sleep))
with integration.make_context(info_name='qontract-reconcile', args=build_args()) as ctx: ctx.ensure_object(dict) ctx.obj['extra_labels'] = extra_labels integration.invoke(ctx) return_code = 0 # This is for when the integration explicitly # calls sys.exit(N) except SystemExit as exc_obj: return_code = int(exc_obj.code) # We have to be generic since we don't know what can happen # in the integrations, but we want to continue the loop anyway except Exception as exc_obj: sleep = SLEEP_ON_ERROR LOG.exception('Error running qontract-reconcile: %s', exc_obj) return_code = ExitCodes.ERROR time_spent = time.monotonic() - start_time run_time.labels(integration=INTEGRATION_NAME, shards=SHARDS, shard_id=SHARD_ID, **extra_labels).set(time_spent) run_status.labels(integration=INTEGRATION_NAME, shards=SHARDS, shard_id=SHARD_ID, **extra_labels).set(return_code) if RUN_ONCE: sys.exit(return_code) time.sleep(int(sleep))