conf.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. # -*- coding: utf-8 -*-
  2. # pylint: disable=C0103,W0622
  3. """
  4. Sphinx documentation for Salt
  5. """
  6. import os
  7. import re
  8. import sys
  9. import time
  10. import types
  11. from sphinx.directives.other import TocTree
  12. class Mock(object):
  13. """
  14. Mock out specified imports.
  15. This allows autodoc to do its thing without having oodles of req'd
  16. installed libs. This doesn't work with ``import *`` imports.
  17. This Mock class can be configured to return a specific values at specific names, if required.
  18. https://read-the-docs.readthedocs.io/en/latest/faq.html#i-get-import-errors-on-libraries-that-depend-on-c-modules
  19. """
  20. def __init__(
  21. self, mapping=None, *args, **kwargs
  22. ): # pylint: disable=unused-argument
  23. """
  24. Mapping allows autodoc to bypass the Mock object, but actually assign
  25. a specific value, expected by a specific attribute returned.
  26. """
  27. self.__mapping = mapping or {}
  28. __all__ = []
  29. def __call__(self, *args, **kwargs):
  30. # If mocked function is used as a decorator, expose decorated function.
  31. # if args and callable(args[-1]):
  32. # functools.update_wrapper(ret, args[0])
  33. return Mock(mapping=self.__mapping)
  34. def __getattr__(self, name):
  35. if name in self.__mapping:
  36. data = self.__mapping.get(name)
  37. elif name in ("__file__", "__path__"):
  38. data = "/dev/null"
  39. elif name in ("__mro_entries__", "__qualname__"):
  40. raise AttributeError("'Mock' object has no attribute '%s'" % (name))
  41. else:
  42. data = Mock(mapping=self.__mapping)
  43. return data
  44. def __iter__(self):
  45. return self
  46. @staticmethod
  47. def __next__():
  48. raise StopIteration
  49. # For Python 2
  50. next = __next__
  51. def mock_decorator_with_params(*oargs, **okwargs): # pylint: disable=unused-argument
  52. """
  53. Optionally mock a decorator that takes parameters
  54. E.g.:
  55. @blah(stuff=True)
  56. def things():
  57. pass
  58. """
  59. def inner(fn, *iargs, **ikwargs): # pylint: disable=unused-argument
  60. if hasattr(fn, "__call__"):
  61. return fn
  62. return Mock()
  63. return inner
  64. MOCK_MODULES = [
  65. # Python stdlib
  66. "user",
  67. # salt core
  68. "Crypto",
  69. "Crypto.Signature",
  70. "Crypto.Cipher",
  71. "Crypto.Hash",
  72. "Crypto.PublicKey",
  73. "Crypto.Random",
  74. "Crypto.Signature",
  75. "Crypto.Signature.PKCS1_v1_5",
  76. "distro",
  77. "M2Crypto",
  78. "msgpack",
  79. "yaml",
  80. "yaml.constructor",
  81. "yaml.nodes",
  82. "yaml.parser",
  83. "yaml.scanner",
  84. "zmq",
  85. "zmq.eventloop",
  86. "zmq.eventloop.ioloop",
  87. # third-party libs for cloud modules
  88. "libcloud",
  89. "libcloud.compute",
  90. "libcloud.compute.base",
  91. "libcloud.compute.deployment",
  92. "libcloud.compute.providers",
  93. "libcloud.compute.types",
  94. "libcloud.loadbalancer",
  95. "libcloud.loadbalancer.types",
  96. "libcloud.loadbalancer.providers",
  97. "libcloud.common",
  98. "libcloud.common.google",
  99. # third-party libs for netapi modules
  100. "cherrypy",
  101. "cherrypy.lib",
  102. "cherrypy.process",
  103. "cherrypy.wsgiserver",
  104. "cherrypy.wsgiserver.ssl_builtin",
  105. "tornado",
  106. "tornado.concurrent",
  107. "tornado.escape",
  108. "tornado.gen",
  109. "tornado.httpclient",
  110. "tornado.httpserver",
  111. "tornado.httputil",
  112. "tornado.ioloop",
  113. "tornado.iostream",
  114. "tornado.netutil",
  115. "tornado.simple_httpclient",
  116. "tornado.stack_context",
  117. "tornado.web",
  118. "tornado.websocket",
  119. "tornado.locks",
  120. "ws4py",
  121. "ws4py.server",
  122. "ws4py.server.cherrypyserver",
  123. "ws4py.websocket",
  124. # modules, renderers, states, returners, et al
  125. "ClusterShell",
  126. "ClusterShell.NodeSet",
  127. "MySQLdb",
  128. "MySQLdb.cursors",
  129. "OpenSSL",
  130. "avahi",
  131. "boto.regioninfo",
  132. "dbus",
  133. "django",
  134. "dns",
  135. "dns.resolver",
  136. "dson",
  137. "hjson",
  138. "jnpr",
  139. "jnpr.junos",
  140. "jnpr.junos.utils",
  141. "jnpr.junos.utils.config",
  142. "jnpr.junos.utils.sw",
  143. "keyring",
  144. "kubernetes",
  145. "kubernetes.config",
  146. "libvirt",
  147. "lxml",
  148. "lxml.etree",
  149. "msgpack",
  150. "nagios_json",
  151. "napalm",
  152. "netaddr",
  153. "netaddr.IPAddress",
  154. "netaddr.core",
  155. "netaddr.core.AddrFormatError",
  156. "ntsecuritycon",
  157. "psutil",
  158. "pycassa",
  159. "pyconnman",
  160. "pyiface",
  161. "pymongo",
  162. "pyroute2",
  163. "pyroute2.ipdb",
  164. "rabbitmq_server",
  165. "redis",
  166. "rpm",
  167. "rpmUtils",
  168. "rpmUtils.arch",
  169. "salt.ext.six.moves.winreg",
  170. "twisted",
  171. "twisted.internet",
  172. "twisted.internet.protocol",
  173. "twisted.internet.protocol.DatagramProtocol",
  174. "win32security",
  175. "yum",
  176. "zfs",
  177. ]
  178. MOCK_MODULES_MAPPING = {
  179. "cherrypy": {"config": mock_decorator_with_params},
  180. "ntsecuritycon": {"STANDARD_RIGHTS_REQUIRED": 0, "SYNCHRONIZE": 0,},
  181. "psutil": {"total": 0}, # Otherwise it will crash Sphinx
  182. }
  183. for mod_name in MOCK_MODULES:
  184. sys.modules[mod_name] = Mock(mapping=MOCK_MODULES_MAPPING.get(mod_name))
  185. # Define a fake version attribute for the following libs.
  186. sys.modules["libcloud"].__version__ = "0.0.0"
  187. sys.modules["msgpack"].version = (1, 0, 0)
  188. sys.modules["psutil"].version_info = (3, 0, 0)
  189. sys.modules["pymongo"].version = "0.0.0"
  190. sys.modules["tornado"].version_info = (0, 0, 0)
  191. sys.modules["boto.regioninfo"]._load_json_file = {"endpoints": None}
  192. # -- Add paths to PYTHONPATH ---------------------------------------------------
  193. try:
  194. docs_basepath = os.path.abspath(os.path.dirname(__file__))
  195. except NameError:
  196. # sphinx-intl and six execute some code which will raise this NameError
  197. # assume we're in the doc/ directory
  198. docs_basepath = os.path.abspath(os.path.dirname("."))
  199. addtl_paths = (
  200. os.pardir, # salt itself (for autodoc)
  201. "_ext", # custom Sphinx extensions
  202. )
  203. for addtl_path in addtl_paths:
  204. sys.path.insert(0, os.path.abspath(os.path.join(docs_basepath, addtl_path)))
  205. # We're now able to import salt
  206. import salt.version # isort:skip
  207. formulas_dir = os.path.join(os.pardir, docs_basepath, "formulas")
  208. # ----- Intersphinx Settings ------------------------------------------------>
  209. intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}
  210. # <---- Intersphinx Settings -------------------------------------------------
  211. # -- General Configuration -----------------------------------------------------
  212. # Set a var if we're building docs for the live site or not
  213. on_saltstack = "SALT_ON_SALTSTACK" in os.environ
  214. project = "Salt"
  215. repo_primary_branch = (
  216. "master" # This is the default branch on GitHub for the Salt project
  217. )
  218. version = salt.version.__version__
  219. latest_release = os.environ.get(
  220. "LATEST_RELEASE", "latest_release"
  221. ) # latest release (2019.2.3)
  222. previous_release = os.environ.get(
  223. "PREVIOUS_RELEASE", "previous_release"
  224. ) # latest release from previous branch (2018.3.5)
  225. previous_release_dir = os.environ.get(
  226. "PREVIOUS_RELEASE_DIR", "previous_release_dir"
  227. ) # path on web server for previous branch (2018.3)
  228. next_release = "" # next release
  229. next_release_dir = "" # path on web server for next release branch
  230. today = ""
  231. copyright = ""
  232. if on_saltstack:
  233. today = (
  234. "Generated on "
  235. + time.strftime("%B %d, %Y")
  236. + " at "
  237. + time.strftime("%X %Z")
  238. + "."
  239. )
  240. copyright = time.strftime("%Y")
  241. # < --- START do not merge these settings to other branches START ---> #
  242. build_type = os.environ.get(
  243. "BUILD_TYPE", repo_primary_branch
  244. ) # latest, previous, master, next
  245. # < --- END do not merge these settings to other branches END ---> #
  246. # Set google custom search engine
  247. if build_type == repo_primary_branch:
  248. release = latest_release
  249. search_cx = "011515552685726825874:v1had6i279q" # master
  250. # search_cx = '011515552685726825874:x17j5zl74g8' # develop
  251. elif build_type == "next":
  252. release = next_release
  253. search_cx = "011515552685726825874:ht0p8miksrm" # latest
  254. elif build_type == "previous":
  255. release = previous_release
  256. if release.startswith("3000"):
  257. search_cx = "011515552685726825874:3skhaozjtyn" # 3000
  258. elif release.startswith("2019.2"):
  259. search_cx = "011515552685726825874:huvjhlpptnm" # 2019.2
  260. elif release.startswith("2018.3"):
  261. search_cx = "011515552685726825874:vadptdpvyyu" # 2018.3
  262. elif release.startswith("2017.7"):
  263. search_cx = "011515552685726825874:w-hxmnbcpou" # 2017.7
  264. elif release.startswith("2016.11"):
  265. search_cx = "011515552685726825874:dlsj745pvhq" # 2016.11
  266. else:
  267. search_cx = "011515552685726825874:ht0p8miksrm" # latest
  268. else: # latest or something else
  269. release = latest_release
  270. search_cx = "011515552685726825874:ht0p8miksrm" # latest
  271. needs_sphinx = "1.3"
  272. spelling_lang = "en_US"
  273. language = "en"
  274. locale_dirs = [
  275. "_locale",
  276. ]
  277. master_doc = "contents"
  278. templates_path = ["_templates"]
  279. exclude_patterns = ["_build", "_incl/*", "ref/cli/_includes/*.rst"]
  280. extensions = [
  281. "saltdomain", # Must come early
  282. "sphinx.ext.autodoc",
  283. "sphinx.ext.napoleon",
  284. "sphinx.ext.autosummary",
  285. "sphinx.ext.extlinks",
  286. "sphinx.ext.intersphinx",
  287. "httpdomain",
  288. "youtube",
  289. "saltrepo"
  290. #'saltautodoc', # Must be AFTER autodoc
  291. #'shorturls',
  292. ]
  293. try:
  294. import sphinxcontrib.spelling # false positive, pylint: disable=unused-import
  295. except ImportError:
  296. pass
  297. else:
  298. extensions += ["sphinxcontrib.spelling"]
  299. modindex_common_prefix = ["salt."]
  300. autosummary_generate = True
  301. autosummary_generate_overwrite = False
  302. # strip git rev as there won't necessarily be a release based on it
  303. stripped_release = re.sub(r"-\d+-g[0-9a-f]+$", "", release)
  304. # Define a substitution for linking to the latest release tarball
  305. rst_prolog = """\
  306. .. |current_release_doc| replace:: :doc:`/topics/releases/{release}`
  307. .. |saltrepo| replace:: https://github.com/saltstack/salt
  308. .. _`salt-users`: https://groups.google.com/forum/#!forum/salt-users
  309. .. _`salt-announce`: https://groups.google.com/forum/#!forum/salt-announce
  310. .. _`salt-packagers`: https://groups.google.com/forum/#!forum/salt-packagers
  311. .. _`salt-slack`: https://saltstackcommunity.herokuapp.com/
  312. .. |windownload| raw:: html
  313. <p>Python2 x86: <a
  314. href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py2-x86-Setup.exe"><strong>Salt-Minion-{release}-x86-Setup.exe</strong></a>
  315. | <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py2-x86-Setup.exe.md5"><strong>md5</strong></a></p>
  316. <p>Python2 AMD64: <a
  317. href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py2-AMD64-Setup.exe"><strong>Salt-Minion-{release}-AMD64-Setup.exe</strong></a>
  318. | <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py2-AMD64-Setup.exe.md5"><strong>md5</strong></a></p>
  319. <p>Python3 x86: <a
  320. href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py3-x86-Setup.exe"><strong>Salt-Minion-{release}-x86-Setup.exe</strong></a>
  321. | <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py3-x86-Setup.exe.md5"><strong>md5</strong></a></p>
  322. <p>Python3 AMD64: <a
  323. href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py3-AMD64-Setup.exe"><strong>Salt-Minion-{release}-AMD64-Setup.exe</strong></a>
  324. | <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py3-AMD64-Setup.exe.md5"><strong>md5</strong></a></p>
  325. .. |osxdownloadpy2| raw:: html
  326. <p>x86_64: <a href="https://repo.saltstack.com/osx/salt-{release}-py2-x86_64.pkg"><strong>salt-{release}-py2-x86_64.pkg</strong></a>
  327. | <a href="https://repo.saltstack.com/osx/salt-{release}-py2-x86_64.pkg.md5"><strong>md5</strong></a></p>
  328. .. |osxdownloadpy3| raw:: html
  329. <p>x86_64: <a href="https://repo.saltstack.com/osx/salt-{release}-py3-x86_64.pkg"><strong>salt-{release}-py3-x86_64.pkg</strong></a>
  330. | <a href="https://repo.saltstack.com/osx/salt-{release}-py3-x86_64.pkg.md5"><strong>md5</strong></a></p>
  331. """.format(
  332. release=stripped_release
  333. )
  334. # A shortcut for linking to tickets on the GitHub issue tracker
  335. extlinks = {
  336. "blob": (
  337. "https://github.com/saltstack/salt/blob/%s/%%s" % repo_primary_branch,
  338. None,
  339. ),
  340. "issue": ("https://github.com/saltstack/salt/issues/%s", "issue #"),
  341. "pull": ("https://github.com/saltstack/salt/pull/%s", "PR #"),
  342. "formula_url": ("https://github.com/saltstack-formulas/%s", ""),
  343. }
  344. # ----- Localization -------------------------------------------------------->
  345. locale_dirs = ["locale/"]
  346. gettext_compact = False
  347. # <---- Localization ---------------------------------------------------------
  348. ### HTML options
  349. # set 'HTML_THEME=saltstack' to use previous theme
  350. html_theme = os.environ.get("HTML_THEME", "saltstack2")
  351. html_theme_path = ["_themes"]
  352. html_title = u""
  353. html_short_title = "Salt"
  354. html_static_path = ["_static"]
  355. html_logo = None # specified in the theme layout.html
  356. html_favicon = "favicon.ico"
  357. smartquotes = False
  358. # Use Google customized search or use Sphinx built-in JavaScript search
  359. if on_saltstack:
  360. html_search_template = "googlesearch.html"
  361. else:
  362. html_search_template = "searchbox.html"
  363. html_additional_pages = {
  364. "404": "404.html",
  365. }
  366. html_default_sidebars = [
  367. html_search_template,
  368. "version.html",
  369. "localtoc.html",
  370. "relations.html",
  371. "sourcelink.html",
  372. "saltstack.html",
  373. ]
  374. html_sidebars = {
  375. "ref/**/all/salt.*": [
  376. html_search_template,
  377. "version.html",
  378. "modules-sidebar.html",
  379. "localtoc.html",
  380. "relations.html",
  381. "sourcelink.html",
  382. "saltstack.html",
  383. ],
  384. "ref/formula/all/*": [],
  385. }
  386. html_context = {
  387. "on_saltstack": on_saltstack,
  388. "html_default_sidebars": html_default_sidebars,
  389. "github_base": "https://github.com/saltstack/salt",
  390. "github_issues": "https://github.com/saltstack/salt/issues",
  391. "github_downloads": "https://github.com/saltstack/salt/downloads",
  392. "latest_release": latest_release,
  393. "previous_release": previous_release,
  394. "previous_release_dir": previous_release_dir,
  395. "next_release": next_release,
  396. "next_release_dir": next_release_dir,
  397. "search_cx": search_cx,
  398. "build_type": build_type,
  399. "today": today,
  400. "copyright": copyright,
  401. "repo_primary_branch": repo_primary_branch,
  402. }
  403. html_use_index = True
  404. html_last_updated_fmt = "%b %d, %Y"
  405. html_show_sourcelink = False
  406. html_show_sphinx = True
  407. html_show_copyright = True
  408. ### Latex options
  409. latex_documents = [
  410. ("contents", "Salt.tex", "Salt Documentation", "SaltStack, Inc.", "manual"),
  411. ]
  412. latex_logo = "_static/salt-logo.png"
  413. latex_elements = {
  414. "inputenc": "", # use XeTeX instead of the inputenc LaTeX package.
  415. "utf8extra": "",
  416. "preamble": r"""
  417. \usepackage{fontspec}
  418. \setsansfont{Linux Biolinum O}
  419. \setromanfont{Linux Libertine O}
  420. \setmonofont{Source Code Pro}
  421. """,
  422. }
  423. ### Linux Biolinum, Linux Libertine: http://www.linuxlibertine.org/
  424. ### Source Code Pro: https://github.com/adobe-fonts/source-code-pro/releases
  425. ### Linkcheck options
  426. linkcheck_ignore = [
  427. r"http://127.0.0.1",
  428. r"http://salt:\d+",
  429. r"http://local:\d+",
  430. r"https://console.aws.amazon.com",
  431. r"http://192.168.33.10",
  432. r"http://domain:\d+",
  433. r"http://123.456.789.012:\d+",
  434. r"http://localhost",
  435. r"https://groups.google.com/forum/#!forum/salt-users",
  436. r"https://www.elastic.co/logstash/docs/latest/inputs/udp",
  437. r"https://www.elastic.co/logstash/docs/latest/inputs/zeromq",
  438. r"http://www.youtube.com/saltstack",
  439. r"https://raven.readthedocs.io",
  440. r"https://getsentry.com",
  441. r"https://salt-cloud.readthedocs.io",
  442. r"https://salt.readthedocs.io",
  443. r"http://www.pip-installer.org/",
  444. r"http://www.windowsazure.com/",
  445. r"https://github.com/watching",
  446. r"dash-feed://",
  447. r"https://github.com/saltstack/salt/",
  448. r"http://bootstrap.saltstack.org",
  449. r"https://bootstrap.saltstack.com",
  450. r"https://raw.githubusercontent.com/saltstack/salt-bootstrap/stable/bootstrap-salt.sh",
  451. r"media.readthedocs.org/dash/salt/latest/salt.xml",
  452. r"https://portal.aws.amazon.com/gp/aws/securityCredentials",
  453. r"https://help.github.com/articles/fork-a-repo",
  454. r"dash-feed://https%3A//media.readthedocs.org/dash/salt/latest/salt.xml",
  455. ]
  456. linkcheck_anchors = False
  457. ### Manpage options
  458. # One entry per manual page. List of tuples
  459. # (source start file, name, description, authors, manual section).
  460. authors = [
  461. "Thomas S. Hatch <thatch45@gmail.com> and many others, please see the Authors file",
  462. ]
  463. man_pages = [
  464. ("contents", "salt", "Salt Documentation", authors, 7),
  465. ("ref/cli/salt", "salt", "salt", authors, 1),
  466. ("ref/cli/salt-master", "salt-master", "salt-master Documentation", authors, 1),
  467. ("ref/cli/salt-minion", "salt-minion", "salt-minion Documentation", authors, 1),
  468. ("ref/cli/salt-key", "salt-key", "salt-key Documentation", authors, 1),
  469. ("ref/cli/salt-cp", "salt-cp", "salt-cp Documentation", authors, 1),
  470. ("ref/cli/salt-call", "salt-call", "salt-call Documentation", authors, 1),
  471. ("ref/cli/salt-proxy", "salt-proxy", "salt-proxy Documentation", authors, 1),
  472. ("ref/cli/salt-syndic", "salt-syndic", "salt-syndic Documentation", authors, 1),
  473. ("ref/cli/salt-run", "salt-run", "salt-run Documentation", authors, 1),
  474. ("ref/cli/salt-ssh", "salt-ssh", "salt-ssh Documentation", authors, 1),
  475. ("ref/cli/salt-cloud", "salt-cloud", "Salt Cloud Command", authors, 1),
  476. ("ref/cli/salt-api", "salt-api", "salt-api Command", authors, 1),
  477. ("ref/cli/salt-unity", "salt-unity", "salt-unity Command", authors, 1),
  478. ("ref/cli/spm", "spm", "Salt Package Manager Command", authors, 1),
  479. ]
  480. ### epub options
  481. epub_title = "Salt Documentation"
  482. epub_author = "SaltStack, Inc."
  483. epub_publisher = epub_author
  484. epub_copyright = copyright
  485. epub_scheme = "URL"
  486. epub_identifier = "http://saltstack.com/"
  487. epub_tocdup = False
  488. # epub_tocdepth = 3
  489. def skip_mod_init_member(app, what, name, obj, skip, options):
  490. # pylint: disable=too-many-arguments,unused-argument
  491. if name.startswith("_"):
  492. return True
  493. if isinstance(obj, types.FunctionType) and obj.__name__ == "mod_init":
  494. return True
  495. return False
  496. def _normalize_version(args):
  497. _, path = args
  498. return ".".join([x.zfill(4) for x in (path.split("/")[-1].split("."))])
  499. class ReleasesTree(TocTree):
  500. option_spec = dict(TocTree.option_spec)
  501. def run(self):
  502. rst = super(ReleasesTree, self).run()
  503. entries = rst[0][0]["entries"][:]
  504. entries.sort(key=_normalize_version, reverse=True)
  505. rst[0][0]["entries"][:] = entries
  506. return rst
  507. def setup(app):
  508. app.add_directive("releasestree", ReleasesTree)
  509. app.connect("autodoc-skip-member", skip_mod_init_member)