conf.py 18 KB

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