conf.py 17 KB

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