mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
0663b23d54
changed zulip-puppet-apply to
use the venv, because it began using `yaml` to parse the output of
puppet to determine if changes would happen.
However, not every install ends with a venv; notably, non-frontend
servers do not have one. Attempting to run zulip-puppet-apply on them
hence now fails.
Remove this dependency on the venv, by installing a system
python3-yaml package -- though in reality, this package is already an
indirect dependency of the system. Especially since pyyaml is quite
stable, we're not using it in any interesting way, and it does not
actually add to the dependencies, it is preferable to parsing the YAML
by hand in this instance.
84 lines
2.8 KiB
Python
Executable File
84 lines
2.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import argparse
|
|
import configparser
|
|
import os
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
|
|
import yaml
|
|
|
|
from lib.zulip_tools import assert_running_as_root, parse_os_release
|
|
|
|
assert_running_as_root()
|
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
parser = argparse.ArgumentParser(description="Run Puppet")
|
|
parser.add_argument(
|
|
"--force", "-f", action="store_true", help="Do not prompt with proposed changes"
|
|
)
|
|
parser.add_argument("--noop", action="store_true", help="Do not apply the changes")
|
|
parser.add_argument("--config", default="/etc/zulip/zulip.conf", help="Alternate zulip.conf path")
|
|
args, extra_args = parser.parse_known_args()
|
|
|
|
config = configparser.RawConfigParser()
|
|
config.read(args.config)
|
|
|
|
distro_info = parse_os_release()
|
|
puppet_config = """
|
|
Exec { path => "/usr/sbin:/usr/bin:/sbin:/bin" }
|
|
"""
|
|
|
|
for pclass in re.split(r"\s*,\s*", config.get("machine", "puppet_classes")):
|
|
puppet_config += f"include {pclass}\n"
|
|
|
|
# We use the Puppet configuration from the same Zulip checkout as this script
|
|
scripts_path = os.path.join(BASE_DIR, "scripts")
|
|
puppet_module_path = os.path.join(BASE_DIR, "puppet")
|
|
puppet_cmd = ["puppet", "apply", f"--modulepath={puppet_module_path}", "-e", puppet_config]
|
|
if args.noop:
|
|
puppet_cmd += ["--noop"]
|
|
puppet_cmd += extra_args
|
|
|
|
# Set the scripts path to be a factor so it can be used by Puppet code
|
|
puppet_env = os.environ.copy()
|
|
puppet_env["FACTER_zulip_conf_path"] = args.config
|
|
puppet_env["FACTER_zulip_scripts_path"] = scripts_path
|
|
|
|
# This is to suppress Puppet warnings with ruby 2.7.
|
|
if (distro_info["ID"], distro_info["VERSION_ID"]) in [("ubuntu", "20.04")]:
|
|
puppet_env["RUBYOPT"] = "-W0"
|
|
|
|
if not args.noop and not args.force:
|
|
# --noop does not work with --detailed-exitcodes; see https://tickets.puppetlabs.com/browse/PUP-686
|
|
try:
|
|
lastrun_file = tempfile.NamedTemporaryFile()
|
|
subprocess.check_call(
|
|
[*puppet_cmd, "--noop", "--show_diff", "--lastrunfile", lastrun_file.name],
|
|
env=puppet_env,
|
|
)
|
|
|
|
with open(lastrun_file.name, "r") as lastrun:
|
|
lastrun_data = yaml.safe_load(lastrun)
|
|
if lastrun_data.get("resources", {}).get("out_of_sync", 0) == 0:
|
|
sys.exit(0)
|
|
finally:
|
|
lastrun_file.close()
|
|
|
|
do_apply = None
|
|
while do_apply != "y":
|
|
sys.stdout.write("Apply changes? [y/N] ")
|
|
sys.stdout.flush()
|
|
do_apply = sys.stdin.readline().strip().lower()
|
|
if do_apply == "" or do_apply == "n":
|
|
sys.exit(0)
|
|
|
|
ret = subprocess.call([*puppet_cmd, "--detailed-exitcodes"], env=puppet_env)
|
|
# ret = 0 => no changes, no errors
|
|
# ret = 2 => changes, no errors
|
|
# ret = 4 => no changes, yes errors
|
|
# ret = 6 => changes, yes errors
|
|
if ret != 0 and ret != 2:
|
|
sys.exit(1)
|