openc3-cosmos-tool-docs 6.3.0 → 6.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/tools/staticdocs/404.html +1 -1
  3. data/tools/staticdocs/assets/images/cosmos-containers-7ecd745840fcff307f0fec01ac4d88a8fa76d531abeae407fee0e508f50a487c.png +0 -0
  4. data/tools/staticdocs/assets/images/cosmos-images-8e15c197653ac3a1f39e8c5eaa56155f364e67d87d66647cff1355b960093af1.png +0 -0
  5. data/tools/staticdocs/assets/js/2bb7bf90.1772f030.js +1 -0
  6. data/tools/staticdocs/assets/js/411898ad.f7b3ff17.js +1 -0
  7. data/tools/staticdocs/assets/js/5b233ba7.9d6ba314.js +1 -0
  8. data/tools/staticdocs/assets/js/6831b732.1318b398.js +1 -0
  9. data/tools/staticdocs/assets/js/696b4199.1e950fcb.js +1 -0
  10. data/tools/staticdocs/assets/js/867640d5.27d9d599.js +1 -0
  11. data/tools/staticdocs/assets/js/89e76475.e1b0dbdb.js +1 -0
  12. data/tools/staticdocs/assets/js/964eb012.0e04c58d.js +1 -0
  13. data/tools/staticdocs/assets/js/9d6e81d0.36405219.js +1 -0
  14. data/tools/staticdocs/assets/js/a677c089.cfa50691.js +1 -0
  15. data/tools/staticdocs/assets/js/a9b2dc27.805dc1ba.js +1 -0
  16. data/tools/staticdocs/assets/js/aa6b6c1b.ef9b0f38.js +1 -0
  17. data/tools/staticdocs/assets/js/b062d239.57d6e194.js +1 -0
  18. data/tools/staticdocs/assets/js/b6d70f94.a9228642.js +1 -0
  19. data/tools/staticdocs/assets/js/c24eae19.0575c394.js +1 -0
  20. data/tools/staticdocs/assets/js/d1b923aa.da892cde.js +1 -0
  21. data/tools/staticdocs/assets/js/d66bf9c0.80a50660.js +1 -0
  22. data/tools/staticdocs/assets/js/d9b92eba.5db8667e.js +1 -0
  23. data/tools/staticdocs/assets/js/{main.8d947189.js → main.a8e2c06c.js} +5 -5
  24. data/tools/staticdocs/assets/js/{runtime~main.d38c5d36.js → runtime~main.7102cb65.js} +1 -1
  25. data/tools/staticdocs/docs/configuration/accessors.html +4 -3
  26. data/tools/staticdocs/docs/configuration/command.html +1 -1
  27. data/tools/staticdocs/docs/configuration/format.html +1 -1
  28. data/tools/staticdocs/docs/configuration/interfaces.html +15 -4
  29. data/tools/staticdocs/docs/configuration/plugins.html +5 -5
  30. data/tools/staticdocs/docs/configuration/protocols.html +7 -6
  31. data/tools/staticdocs/docs/configuration/ssl-tls.html +115 -76
  32. data/tools/staticdocs/docs/configuration/table.html +1 -1
  33. data/tools/staticdocs/docs/configuration/target.html +1 -1
  34. data/tools/staticdocs/docs/configuration/telemetry-screens.html +1 -1
  35. data/tools/staticdocs/docs/configuration/telemetry.html +1 -1
  36. data/tools/staticdocs/docs/configuration.html +1 -1
  37. data/tools/staticdocs/docs/development/curl.html +4 -4
  38. data/tools/staticdocs/docs/development/developing.html +2 -2
  39. data/tools/staticdocs/docs/development/json-api.html +1 -1
  40. data/tools/staticdocs/docs/development/log-structure.html +1 -1
  41. data/tools/staticdocs/docs/development/roadmap.html +1 -1
  42. data/tools/staticdocs/docs/development/streaming-api.html +1 -1
  43. data/tools/staticdocs/docs/development/testing.html +1 -1
  44. data/tools/staticdocs/docs/development.html +1 -1
  45. data/tools/staticdocs/docs/getting-started/cli.html +2 -2
  46. data/tools/staticdocs/docs/getting-started/generators.html +2 -2
  47. data/tools/staticdocs/docs/getting-started/gettingstarted.html +1 -1
  48. data/tools/staticdocs/docs/getting-started/installation.html +1 -1
  49. data/tools/staticdocs/docs/getting-started/key-concepts.html +8 -4
  50. data/tools/staticdocs/docs/getting-started/podman.html +1 -1
  51. data/tools/staticdocs/docs/getting-started/requirements.html +1 -1
  52. data/tools/staticdocs/docs/getting-started/upgrading.html +1 -1
  53. data/tools/staticdocs/docs/getting-started.html +1 -1
  54. data/tools/staticdocs/docs/guides/bridges.html +1 -1
  55. data/tools/staticdocs/docs/guides/cfs.html +12 -12
  56. data/tools/staticdocs/docs/guides/custom-widgets.html +1 -1
  57. data/tools/staticdocs/docs/guides/dynamic-packets.html +1 -1
  58. data/tools/staticdocs/docs/guides/exposing-microservices.html +4 -4
  59. data/tools/staticdocs/docs/guides/little-endian-bitfields.html +1 -1
  60. data/tools/staticdocs/docs/guides/local-mode.html +1 -1
  61. data/tools/staticdocs/docs/guides/logging.html +1 -1
  62. data/tools/staticdocs/docs/guides/monitoring.html +1 -1
  63. data/tools/staticdocs/docs/guides/performance.html +6 -6
  64. data/tools/staticdocs/docs/guides/raspberrypi.html +1 -1
  65. data/tools/staticdocs/docs/guides/script-writing.html +1 -1
  66. data/tools/staticdocs/docs/guides/scripting-api.html +55 -16
  67. data/tools/staticdocs/docs/guides.html +1 -1
  68. data/tools/staticdocs/docs/meta/contributing.html +1 -1
  69. data/tools/staticdocs/docs/meta/licenses.html +8 -8
  70. data/tools/staticdocs/docs/meta/philosophy.html +2 -2
  71. data/tools/staticdocs/docs/meta/xtce.html +1 -1
  72. data/tools/staticdocs/docs/meta.html +1 -1
  73. data/tools/staticdocs/docs/privacy.html +1 -1
  74. data/tools/staticdocs/docs/tools/admin.html +1 -1
  75. data/tools/staticdocs/docs/tools/autonomic.html +1 -1
  76. data/tools/staticdocs/docs/tools/bucket-explorer.html +2 -2
  77. data/tools/staticdocs/docs/tools/calendar.html +1 -1
  78. data/tools/staticdocs/docs/tools/cmd-sender.html +1 -1
  79. data/tools/staticdocs/docs/tools/cmd-tlm-server.html +1 -1
  80. data/tools/staticdocs/docs/tools/command_history.html +1 -1
  81. data/tools/staticdocs/docs/tools/data-extractor.html +1 -1
  82. data/tools/staticdocs/docs/tools/data-viewer.html +1 -1
  83. data/tools/staticdocs/docs/tools/handbooks.html +1 -1
  84. data/tools/staticdocs/docs/tools/limits-monitor.html +1 -1
  85. data/tools/staticdocs/docs/tools/packet-viewer.html +1 -1
  86. data/tools/staticdocs/docs/tools/script-runner.html +1 -1
  87. data/tools/staticdocs/docs/tools/table-manager.html +1 -1
  88. data/tools/staticdocs/docs/tools/tlm-grapher.html +1 -1
  89. data/tools/staticdocs/docs/tools/tlm-viewer.html +1 -1
  90. data/tools/staticdocs/docs/tools.html +1 -1
  91. data/tools/staticdocs/docs.html +1 -1
  92. data/tools/staticdocs/img/cosmos-containers.png +0 -0
  93. data/tools/staticdocs/img/cosmos-images.png +0 -0
  94. data/tools/staticdocs/index.html +1 -1
  95. data/tools/staticdocs/lunr-index-1746647301890.json +1 -0
  96. data/tools/staticdocs/lunr-index.json +1 -1
  97. data/tools/staticdocs/markdown-page.html +1 -1
  98. data/tools/staticdocs/search-doc-1746647301890.json +1 -0
  99. data/tools/staticdocs/search-doc.json +1 -1
  100. metadata +28 -24
  101. data/tools/staticdocs/assets/js/2bb7bf90.4a658ce6.js +0 -1
  102. data/tools/staticdocs/assets/js/411898ad.f7fc4d80.js +0 -1
  103. data/tools/staticdocs/assets/js/5b233ba7.2ea0179c.js +0 -1
  104. data/tools/staticdocs/assets/js/6831b732.0a867cbc.js +0 -1
  105. data/tools/staticdocs/assets/js/696b4199.2a7ff897.js +0 -1
  106. data/tools/staticdocs/assets/js/867640d5.2c0fa6d9.js +0 -1
  107. data/tools/staticdocs/assets/js/89e76475.a76d0072.js +0 -1
  108. data/tools/staticdocs/assets/js/964eb012.dbc2c206.js +0 -1
  109. data/tools/staticdocs/assets/js/9d6e81d0.44e2d544.js +0 -1
  110. data/tools/staticdocs/assets/js/a677c089.18f98b70.js +0 -1
  111. data/tools/staticdocs/assets/js/a9b2dc27.e01c9bb4.js +0 -1
  112. data/tools/staticdocs/assets/js/aa6b6c1b.3aad95fc.js +0 -1
  113. data/tools/staticdocs/assets/js/b062d239.535a2ceb.js +0 -1
  114. data/tools/staticdocs/assets/js/b6d70f94.7813125e.js +0 -1
  115. data/tools/staticdocs/assets/js/c24eae19.aaae7796.js +0 -1
  116. data/tools/staticdocs/assets/js/d1b923aa.a73e7e79.js +0 -1
  117. data/tools/staticdocs/assets/js/d66bf9c0.842d2efa.js +0 -1
  118. data/tools/staticdocs/assets/js/d9b92eba.34e63ba6.js +0 -1
  119. data/tools/staticdocs/lunr-index-1743825503427.json +0 -1
  120. data/tools/staticdocs/search-doc-1743825503427.json +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ad96c9d6154921577641d9653a59dc24d6f1f6d72cf6f77cd03c907c301e27d6
4
- data.tar.gz: 16b83187a79abfc76b2e2c1110946e974bdfc77748547239bd7b0bf7b8f12942
3
+ metadata.gz: d4463b2d8149f3392872a36883aff8a9fb441e9dad90db9192aae86dd3ea7df1
4
+ data.tar.gz: fe6e094bab9d9c9291dcb431255b3261f40d9c2ee42b1f3aa915ffda992ce121
5
5
  SHA512:
6
- metadata.gz: 2de68003415e058c89c95572b78ca5b3a83e01afd68bcd58438a2b3403e31f8fcf169c83942627eb42645a6b3cd060495ad14c218f212b3d03b9095928d5a632
7
- data.tar.gz: 5b5b6fe24a422e968caec6ccb396bca40dd636b2242b222e31c100f7ec3ebe9a0f8290220e5a79659bb667ded4f00101b5553476b281e25b74f2521282a41806
6
+ metadata.gz: 973b952e7845e9a687e64ce90c84519760439ecf98a1073e8302c92ceede61c5fd72300d4846e4deea5850c152abb155177c3cb6c2a57426b2b0d642380bf3c9
7
+ data.tar.gz: 74594154bc51e20ddc0c891e84ebdace92a137ed324115208b612c76c73c987010475766e133727fb6a682b72fed1cbe2e54e58189475159b5b79a47d71eee52
@@ -1 +1 @@
1
- <!doctype html><html lang=en dir=ltr class="plugin-native plugin-id-default" data-has-hydrated=false><meta charset=UTF-8><meta name=generator content="Docusaurus v3.7.0"><title data-rh=true>Page Not Found | OpenC3 Docs</title><meta data-rh=true name=viewport content="width=device-width, initial-scale=1.0"><meta data-rh=true name=twitter:card content=summary_large_image><meta data-rh=true property=og:url content=https://docs.openc3.com/tools/staticdocs/404.html><meta data-rh=true property=og:locale content=en><meta data-rh=true name=docusaurus_locale content=en><meta data-rh=true name=docusaurus_tag content=default><meta data-rh=true name=docsearch:language content=en><meta data-rh=true name=docsearch:docusaurus_tag content=default><meta data-rh=true property=og:title content="Page Not Found | OpenC3 Docs"><link data-rh=true rel=icon href=/tools/staticdocs/img/favicon.png><link data-rh=true rel=canonical href=https://docs.openc3.com/tools/staticdocs/404.html><link data-rh=true rel=alternate href=https://docs.openc3.com/tools/staticdocs/404.html hreflang=en><link data-rh=true rel=alternate href=https://docs.openc3.com/tools/staticdocs/404.html hreflang=x-default><link rel=stylesheet href=/tools/staticdocs/assets/css/styles.1de6b959.css><script src=/tools/staticdocs/assets/js/runtime~main.d38c5d36.js defer></script><script src=/tools/staticdocs/assets/js/main.8d947189.js defer></script><body class=navigation-with-keyboard><script>!function(){var t,e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();t=null!==e?e:"dark",document.documentElement.setAttribute("data-theme",t)}(),function(){try{for(var[t,e]of new URLSearchParams(window.location.search).entries())if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id=__docusaurus><link rel=preload as=image href=/tools/staticdocs/img/logo.svg><div role=region aria-label="Skip to main content"><a class=skipToContent_G6ar href=#__docusaurus_skipToContent_fallback>Skip to main content</a></div><nav aria-label=Main class="navbar navbar--fixed-top"><div class=navbar__inner><div class=navbar__items><button aria-label="Toggle navigation bar" aria-expanded=false class="navbar__toggle clean-btn" type=button><svg width=30 height=30 viewBox="0 0 30 30" aria-hidden=true><path stroke=currentColor stroke-linecap=round stroke-miterlimit=10 stroke-width=2 d="M4 7h22M4 15h22M4 23h22"/></svg></button><a class=navbar__brand href=/tools/staticdocs/><div class=navbar__logo><img src=/tools/staticdocs/img/logo.svg alt="OpenC3 Logo" class="themedComponent_DHUr themedComponent--light_DIHH"><img src=/tools/staticdocs/img/logo.svg alt="OpenC3 Logo" class="themedComponent_DHUr themedComponent--dark_Bv2M"></div><b class="navbar__title text--truncate">OpenC3 Docs</b></a><a class="navbar__item navbar__link" href=/tools/staticdocs/docs>Documentation</a><a href=https://openc3.com/enterprise/ target=_blank rel="noopener noreferrer" class="navbar__item navbar__link">Enterprise</a></div><div class="navbar__items navbar__items--right"><div class=navbarSearchContainer_bmvg><div class=navbar__search><span aria-label="expand searchbar" role=button class=search-icon tabindex=0></span><input id=search_input_react type=search placeholder=Loading... aria-label=Search class="navbar__search-input search-bar" disabled></div></div></div></div><div role=presentation class=navbar-sidebar__backdrop></div></nav><div id=__docusaurus_skipToContent_fallback class="main-wrapper mainWrapper_UyTV"><main class="container margin-vert--xl"><div class=row><div class="col col--6 col--offset-3"><h1 class=hero__title>Page Not Found</h1><p>We could not find what you were looking for.<p>Please contact the owner of the site that linked you to the original URL and let them know their link is broken.</div></div></main></div><footer class="footer footer--dark"><div class="container container-fluid"><div class="row footer__links"><div class="col footer__col"><div class=footer__title>Homepage</div><ul class="footer__items clean-list"><li class=footer__item><a href=https://openc3.com target=_blank rel="noopener noreferrer" class=footer__link-item>Home</a></ul></div><div class="col footer__col"><div class=footer__title>Docs</div><ul class="footer__items clean-list"><li class=footer__item><a class=footer__link-item href=/tools/staticdocs/docs>Documentation</a></ul></div><div class="col footer__col"><div class=footer__title>Community</div><ul class="footer__items clean-list"><li class=footer__item><a href=https://www.linkedin.com/company/openc3 target=_blank rel="noopener noreferrer" class=footer__link-item>LinkedIn<svg width=13.5 height=13.5 aria-hidden=true viewBox="0 0 24 24" class=iconExternalLink_awgD><path fill=currentColor d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></svg></a></ul></div><div class="col footer__col"><div class=footer__title>More</div><ul class="footer__items clean-list"><li class=footer__item><a href=https://github.com/OpenC3/cosmos target=_blank rel="noopener noreferrer" class=footer__link-item>GitHub<svg width=13.5 height=13.5 aria-hidden=true viewBox="0 0 24 24" class=iconExternalLink_awgD><path fill=currentColor d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></svg></a><li class=footer__item><a class=footer__link-item href=/tools/staticdocs/docs/privacy>Privacy</a></ul></div></div><div class="footer__bottom text--center"><div class=footer__copyright>Copyright © 2025 OpenC3, Inc.</div></div></div></footer></div>
1
+ <!doctype html><html lang=en dir=ltr class="plugin-native plugin-id-default" data-has-hydrated=false><meta charset=UTF-8><meta name=generator content="Docusaurus v3.7.0"><title data-rh=true>Page Not Found | OpenC3 Docs</title><meta data-rh=true name=viewport content="width=device-width, initial-scale=1.0"><meta data-rh=true name=twitter:card content=summary_large_image><meta data-rh=true property=og:url content=https://docs.openc3.com/tools/staticdocs/404.html><meta data-rh=true property=og:locale content=en><meta data-rh=true name=docusaurus_locale content=en><meta data-rh=true name=docusaurus_tag content=default><meta data-rh=true name=docsearch:language content=en><meta data-rh=true name=docsearch:docusaurus_tag content=default><meta data-rh=true property=og:title content="Page Not Found | OpenC3 Docs"><link data-rh=true rel=icon href=/tools/staticdocs/img/favicon.png><link data-rh=true rel=canonical href=https://docs.openc3.com/tools/staticdocs/404.html><link data-rh=true rel=alternate href=https://docs.openc3.com/tools/staticdocs/404.html hreflang=en><link data-rh=true rel=alternate href=https://docs.openc3.com/tools/staticdocs/404.html hreflang=x-default><link rel=stylesheet href=/tools/staticdocs/assets/css/styles.1de6b959.css><script src=/tools/staticdocs/assets/js/runtime~main.7102cb65.js defer></script><script src=/tools/staticdocs/assets/js/main.a8e2c06c.js defer></script><body class=navigation-with-keyboard><script>!function(){var t,e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();t=null!==e?e:"dark",document.documentElement.setAttribute("data-theme",t)}(),function(){try{for(var[t,e]of new URLSearchParams(window.location.search).entries())if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id=__docusaurus><link rel=preload as=image href=/tools/staticdocs/img/logo.svg><div role=region aria-label="Skip to main content"><a class=skipToContent_G6ar href=#__docusaurus_skipToContent_fallback>Skip to main content</a></div><nav aria-label=Main class="navbar navbar--fixed-top"><div class=navbar__inner><div class=navbar__items><button aria-label="Toggle navigation bar" aria-expanded=false class="navbar__toggle clean-btn" type=button><svg width=30 height=30 viewBox="0 0 30 30" aria-hidden=true><path stroke=currentColor stroke-linecap=round stroke-miterlimit=10 stroke-width=2 d="M4 7h22M4 15h22M4 23h22"/></svg></button><a class=navbar__brand href=/tools/staticdocs/><div class=navbar__logo><img src=/tools/staticdocs/img/logo.svg alt="OpenC3 Logo" class="themedComponent_DHUr themedComponent--light_DIHH"><img src=/tools/staticdocs/img/logo.svg alt="OpenC3 Logo" class="themedComponent_DHUr themedComponent--dark_Bv2M"></div><b class="navbar__title text--truncate">OpenC3 Docs</b></a><a class="navbar__item navbar__link" href=/tools/staticdocs/docs>Documentation</a><a href=https://openc3.com/enterprise/ target=_blank rel="noopener noreferrer" class="navbar__item navbar__link">Enterprise</a></div><div class="navbar__items navbar__items--right"><div class=navbarSearchContainer_bmvg><div class=navbar__search><span aria-label="expand searchbar" role=button class=search-icon tabindex=0></span><input id=search_input_react type=search placeholder=Loading... aria-label=Search class="navbar__search-input search-bar" disabled></div></div></div></div><div role=presentation class=navbar-sidebar__backdrop></div></nav><div id=__docusaurus_skipToContent_fallback class="main-wrapper mainWrapper_UyTV"><main class="container margin-vert--xl"><div class=row><div class="col col--6 col--offset-3"><h1 class=hero__title>Page Not Found</h1><p>We could not find what you were looking for.<p>Please contact the owner of the site that linked you to the original URL and let them know their link is broken.</div></div></main></div><footer class="footer footer--dark"><div class="container container-fluid"><div class="row footer__links"><div class="col footer__col"><div class=footer__title>Homepage</div><ul class="footer__items clean-list"><li class=footer__item><a href=https://openc3.com target=_blank rel="noopener noreferrer" class=footer__link-item>Home</a></ul></div><div class="col footer__col"><div class=footer__title>Docs</div><ul class="footer__items clean-list"><li class=footer__item><a class=footer__link-item href=/tools/staticdocs/docs>Documentation</a></ul></div><div class="col footer__col"><div class=footer__title>Community</div><ul class="footer__items clean-list"><li class=footer__item><a href=https://www.linkedin.com/company/openc3 target=_blank rel="noopener noreferrer" class=footer__link-item>LinkedIn<svg width=13.5 height=13.5 aria-hidden=true viewBox="0 0 24 24" class=iconExternalLink_awgD><path fill=currentColor d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></svg></a></ul></div><div class="col footer__col"><div class=footer__title>More</div><ul class="footer__items clean-list"><li class=footer__item><a href=https://github.com/OpenC3/cosmos target=_blank rel="noopener noreferrer" class=footer__link-item>GitHub<svg width=13.5 height=13.5 aria-hidden=true viewBox="0 0 24 24" class=iconExternalLink_awgD><path fill=currentColor d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></svg></a><li class=footer__item><a class=footer__link-item href=/tools/staticdocs/docs/privacy>Privacy</a></ul></div></div><div class="footer__bottom text--center"><div class=footer__copyright>Copyright © 2025 OpenC3, Inc.</div></div></div></footer></div>
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([["7637"],{2695:function(e,t,n){n.r(t),n.d(t,{default:()=>h,frontMatter:()=>o,metadata:()=>s,assets:()=>l,toc:()=>c,contentTitle:()=>a});var s=JSON.parse('{"id":"getting-started/generators","title":"Code Generators","description":"Using openc3.sh to generate code","source":"@site/docs/getting-started/generators.md","sourceDirName":"getting-started","slug":"/getting-started/generators","permalink":"/tools/staticdocs/docs/getting-started/generators","draft":false,"unlisted":false,"editUrl":"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/getting-started/generators.md","tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"sidebar_position":6,"title":"Code Generators","description":"Using openc3.sh to generate code","sidebar_custom_props":{"myEmoji":"\uD83C\uDFED"}},"sidebar":"defaultSidebar","previous":{"title":"Command Line Interface","permalink":"/tools/staticdocs/docs/getting-started/cli"},"next":{"title":"Podman","permalink":"/tools/staticdocs/docs/getting-started/podman"}}'),i=n("2322"),r=n("2840");let o={sidebar_position:6,title:"Code Generators",description:"Using openc3.sh to generate code",sidebar_custom_props:{myEmoji:"\uD83C\uDFED"}},a=void 0,l={},c=[{value:"Plugin Generator",id:"plugin-generator",level:2},{value:"Target Generator",id:"target-generator",level:2},{value:"Microservice Generator",id:"microservice-generator",level:2},{value:"Conversion Generator",id:"conversion-generator",level:2},{value:"Limits Response Generator",id:"limits-response-generator",level:2},{value:"Widget Generator",id:"widget-generator",level:2},{value:"Tool Generator",id:"tool-generator",level:2}];function d(e){let t={a:"a",admonition:"admonition",code:"code",h2:"h2",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["The COSMOS Code Generators are built into the scripts ",(0,i.jsx)(t.code,{children:"openc3.sh"})," and ",(0,i.jsx)(t.code,{children:"openc3.bat"})," that are included in the COSMOS ",(0,i.jsx)(t.a,{href:"https://github.com/OpenC3/cosmos-project",children:"project"})," (more about ",(0,i.jsx)(t.a,{href:"key-concepts#projects",children:"projects"}),")."]}),"\n",(0,i.jsxs)(t.p,{children:["If you followed the ",(0,i.jsx)(t.a,{href:"/tools/staticdocs/docs/getting-started/installation",children:"Installation Guide"})," you should already be inside a cloned ",(0,i.jsx)(t.a,{href:"https://github.com/OpenC3/cosmos-project",children:"openc3-project"})," which is in your PATH (necessary for openc3.bat / openc3.sh to be resolved). To see all the available code generators type the following:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"% openc3.sh cli generate\nUnknown generator ''. Valid generators: plugin, target, microservice, widget, conversion,\nlimits_response, tool, tool_vue, tool_angular, tool_react, tool_svelte\n"})}),"\n",(0,i.jsx)(t.admonition,{title:"Training Available",type:"note",children:(0,i.jsxs)(t.p,{children:["If any of this gets confusing, contact us at ",(0,i.jsx)("a",{href:"mailto:support@openc3.com",children:(0,i.jsx)(t.a,{href:"mailto:support@openc3.com",children:"support@openc3.com"})}),". We have training classes available!"]})}),"\n",(0,i.jsx)(t.h2,{id:"plugin-generator",children:"Plugin Generator"}),"\n",(0,i.jsxs)(t.p,{children:["The plugin generator creates the scaffolding for a new COSMOS Plugin. It requires a plugin name and will create a new directory called ",(0,i.jsx)(t.code,{children:"openc3-cosmos-<name>"}),". For example:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"% openc3.sh cli generate plugin\nUsage: cli generate plugin <NAME>\n\n% openc3.sh cli generate plugin GSE\nPlugin openc3-cosmos-gse successfully generated!\n"})}),"\n",(0,i.jsx)(t.p,{children:"This creates the following files:"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"Name"}),(0,i.jsx)(t.th,{children:"Description"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:".gitignore"}),(0,i.jsx)(t.td,{children:"Tells git to ignore any node_modules directory (for tool development)"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"LICENSE.txt"}),(0,i.jsx)(t.td,{children:"License for the plugin. COSMOS Plugins should be licensed in a manner compatible with the AGPLv3, unless they are designed only for use with COSMOS Enterprise."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"openc3-cosmos-gse.gemspec"}),(0,i.jsxs)(t.td,{children:["Gemspec file which should be edited to add user specific information like description, authors, emails, homepage, etc. The name of this file is used in compiling the plugin contents into the final corresponding gem file: e.g. openc3-cosmos-gse-1.0.0.gem. COSMOS plugins should always begin with the openc3-cosmos prefix to make them easily identifiable in the Rubygems repository. The file is formatted as documented at: ",(0,i.jsx)(t.a,{href:"https://guides.rubygems.org/specification-reference/",children:"https://guides.rubygems.org/specification-reference/"})]})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"plugin.txt"}),(0,i.jsxs)(t.td,{children:["COSMOS specific file for Plugin creation. Learn more ",(0,i.jsx)(t.a,{href:"../configuration/plugins",children:"here"}),"."]})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"Rakefile"}),(0,i.jsx)(t.td,{children:'Ruby Rakefile configured to support building the plugin by running "openc3.sh cli rake build VERSION=X.X.X" where X.X.X is the plugin version number'})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"README.md"}),(0,i.jsx)(t.td,{children:"Markdown file used to document the plugin"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"requirements.txt"}),(0,i.jsx)(t.td,{children:"Python dependencies file (only for Python plugins)"})]})]})]}),"\n",(0,i.jsx)(t.p,{children:"While this structure is required, it is not very useful by itself. The plugin generator just creates the framework for other generators to use."}),"\n",(0,i.jsx)(t.h2,{id:"target-generator",children:"Target Generator"}),"\n",(0,i.jsx)(t.p,{children:"The target generator creates the scaffolding for a new COSMOS Target. It must operate inside an existing COSMOS plugin and requires a target name. For example:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate target\nUsage: cli generate target <NAME> (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate target GSE\nTarget GSE successfully generated!\n"})}),"\n",(0,i.jsx)(t.p,{children:"This creates the following files and directories:"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"Name"}),(0,i.jsx)(t.th,{children:"Description"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE"}),(0,i.jsx)(t.td,{children:"Contains the configuration for the GSE target. The target name is always defined in all caps. This is typically the default name of the target, but well-designed targets will allow themselves to be renamed at installation."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/cmd_tlm"}),(0,i.jsx)(t.td,{children:"Contains the command and telemetry definition files for the GSE target. These files capture the format of the commands that can be sent to the target, and the telemetry packets that are expected to be received by COSMOS from the target. Note that the files in this folder are processed in alphabetical order by default. That can matter if you reference a packet in another file (it must already have been defined)."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/cmd_tlm/cmd.txt"}),(0,i.jsxs)(t.td,{children:["Example ",(0,i.jsx)(t.a,{href:"../configuration/command",children:"command"})," configuration. Will need to be edited for the target specific commands."]})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/cmd_tlm/tlm.txt"}),(0,i.jsxs)(t.td,{children:["Example ",(0,i.jsx)(t.a,{href:"../configuration/telemetry",children:"telemetry"})," configuration. Will need to be edited for the target specific telemetry."]})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/lib"}),(0,i.jsxs)(t.td,{children:["Contains any custom code required by the target. Good examples of custom code are library files, custom ",(0,i.jsx)(t.a,{href:"../configuration/interfaces",children:"interface"})," classes and ",(0,i.jsx)(t.a,{href:"../configuration/protocols",children:"protocols"}),"."]})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/lib/gse.rb/py"}),(0,i.jsx)(t.td,{children:"Example library file which can be expanded as the target is developed. COSMOS recommends building up library methods to avoid code duplication and ease reuse."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/procedures"}),(0,i.jsxs)(t.td,{children:["This folder contains target specific procedures and helper methods which exercise functionality of the target. These procedures should be kept simple and only use the command and telemetry definitions associated with this target. See the ",(0,i.jsx)(t.a,{href:"../guides/script-writing#script-organization",children:"Scripting Guide"})," for more information."]})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/procedures/procedure.rb/py"}),(0,i.jsx)(t.td,{children:"Procedure with an example of sending a command and checking telemetry"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/public"}),(0,i.jsxs)(t.td,{children:["Put image files here for use in Telemetry Viewer Canvas Image widgets such as ",(0,i.jsx)(t.a,{href:"/tools/staticdocs/docs/configuration/telemetry-screens#canvasimage",children:"CANVASIMAGE"})," and ",(0,i.jsx)(t.a,{href:"/tools/staticdocs/docs/configuration/telemetry-screens#canvasimagevalue",children:"CANVASIMAGEVALUE"})]})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/screens"}),(0,i.jsxs)(t.td,{children:["Contains telemetry ",(0,i.jsx)(t.a,{href:"/tools/staticdocs/docs/configuration/telemetry-screens",children:"screens"})," for the target"]})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/screens/status.txt"}),(0,i.jsxs)(t.td,{children:["Example ",(0,i.jsx)(t.a,{href:"/tools/staticdocs/docs/configuration/telemetry-screens",children:"screen"})," to display telemetry values"]})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/target.txt"}),(0,i.jsxs)(t.td,{children:[(0,i.jsx)(t.a,{href:"../configuration/target",children:"Target"})," configuration such as ignoring command and telemetry items and how to process the cmd/tlm files"]})]})]})]}),"\n",(0,i.jsx)(t.p,{children:"It also updates the plugin.txt file to add the new target:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ruby",children:"VARIABLE gse_target_name GSE\n\nTARGET GSE <%= gse_target_name %>\nINTERFACE <%= gse_target_name %>_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET <%= gse_target_name %>\n"})}),"\n",(0,i.jsx)(t.h2,{id:"microservice-generator",children:"Microservice Generator"}),"\n",(0,i.jsx)(t.p,{children:"The microservice generator creates the scaffolding for a new COSMOS Microservice. It must operate inside an existing COSMOS plugin and requires a target name. For example:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate microservice\nUsage: cli generate microservice <NAME> (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate microservice background\nMicroservice BACKGROUND successfully generated!\n"})}),"\n",(0,i.jsx)(t.p,{children:"This creates the following files and directories:"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"Name"}),(0,i.jsx)(t.th,{children:"Description"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"microservices/BACKGROUND"}),(0,i.jsx)(t.td,{children:"Contains the code and any necessary configuration for the BACKGROUND microservice. The name is always defined in all caps. This is typically the default name of the microservice, but well-designed microservices will allow themselves to be renamed at installation."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"microservices/BACKGROUND/background.rb"}),(0,i.jsx)(t.td,{children:"Fully functional microservice which will run every minute and log a message. Edit to implement any custom logic that you want to run in the background. Potential uses are safety microservices which can check and autonomously respond to complex events and take action (NOTE: Simple actions might just require a Limits Response)."})]})]})]}),"\n",(0,i.jsx)(t.p,{children:"It also updates the plugin.txt file to add the new microservice:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ruby",children:"MICROSERVICE BACKGROUND background-microservice\n CMD ruby background.rb\n"})}),"\n",(0,i.jsx)(t.h2,{id:"conversion-generator",children:"Conversion Generator"}),"\n",(0,i.jsxs)(t.p,{children:["The conversion generator creates the scaffolding for a new COSMOS ",(0,i.jsx)(t.a,{href:"../configuration/telemetry#read_conversion",children:"Conversion"}),". It must operate inside an existing COSMOS plugin and requires both a target name and conversion name. For example:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate conversion\nUsage: cli generate conversion <TARGET> <NAME> (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate limits_response GSE double\nConversion targets/GSE/lib/double_conversion.rb successfully generated!\nTo use the conversion add the following to a telemetry item:\n READ_CONVERSION double_conversion.rb\n"})}),"\n",(0,i.jsx)(t.p,{children:"This creates the following files and directories:"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"Name"}),(0,i.jsx)(t.th,{children:"Description"})]})}),(0,i.jsx)(t.tbody,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/lib/double_conversion.rb"}),(0,i.jsx)(t.td,{children:"Fully functional Conversion which has an example implementation of the call() method to convert any existing COSMOS values."})]})})]}),"\n",(0,i.jsx)(t.p,{children:"As the generator states, to use this conversion code you must add it to a telemetry item. For example:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ruby",children:'TELEMETRY GSE STATUS BIG_ENDIAN "Telemetry description"\n # Keyword Name BitSize Type ID Description\n APPEND_ID_ITEM ID 16 INT 1 "Identifier"\n APPEND_ITEM VALUE 32 FLOAT "Value"\n READ_CONVERSION double_conversion.rb\n APPEND_ITEM BOOL 8 UINT "Boolean"\n STATE FALSE 0\n STATE TRUE 1\n APPEND_ITEM LABEL 0 STRING "The label to apply"\n'})}),"\n",(0,i.jsx)(t.h2,{id:"limits-response-generator",children:"Limits Response Generator"}),"\n",(0,i.jsxs)(t.p,{children:["The limits_response generator creates the scaffolding for a new COSMOS ",(0,i.jsx)(t.a,{href:"../configuration/telemetry#limits_response",children:"Limits Response"}),". It must operate inside an existing COSMOS plugin and requires both a target name and limits response name. For example:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate limits_response\nUsage: cli generate limits_response <TARGET> <NAME> (--ruby or --python)\n\nopenc3-cosmos-gse % openc3.sh cli generate limits_response GSE safe\nLimits response targets/GSE/lib/safe_limits_response.rb successfully generated!\nTo use the limits response add the following to a telemetry item:\n LIMITS_RESPONSE safe_limits_response.rb\n"})}),"\n",(0,i.jsx)(t.p,{children:"This creates the following files and directories:"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"Name"}),(0,i.jsx)(t.th,{children:"Description"})]})}),(0,i.jsx)(t.tbody,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"targets/GSE/lib/safe_limits_response.rb"}),(0,i.jsx)(t.td,{children:"Fully functional Limits Response which has an example implementation of the call() method and taking action based on the current limits state of the particular item"})]})})]}),"\n",(0,i.jsx)(t.p,{children:"As the generator states, to use this limits code you must add it to a telemetry item which has limits defined. In the generated GSE target, none of the items have limits defined so you first need to add limits and then add the response."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ruby",children:'TELEMETRY GSE STATUS BIG_ENDIAN "Telemetry description"\n # Keyword Name BitSize Type ID Description\n APPEND_ID_ITEM ID 16 INT 1 "Identifier"\n APPEND_ITEM VALUE 32 FLOAT "Value"\n LIMITS DEFAULT 1 ENABLED -80.0 -70.0 60.0 80.0 -20.0 20.0\n LIMITS_RESPONSE safe_limits_response.rb\n APPEND_ITEM BOOL 8 UINT "Boolean"\n STATE FALSE 0\n STATE TRUE 1\n APPEND_ITEM LABEL 0 STRING "The label to apply"\n'})}),"\n",(0,i.jsx)(t.h2,{id:"widget-generator",children:"Widget Generator"}),"\n",(0,i.jsxs)(t.p,{children:["The conversion generator creates the scaffolding for a new COSMOS Widget for use in ",(0,i.jsx)(t.a,{href:"../configuration/telemetry-screens",children:"Telemetry Viewer Screens"}),". For more information see the ",(0,i.jsx)(t.a,{href:"../guides/custom-widgets",children:"Custom Widget"})," guide. It must operate inside an existing COSMOS plugin and requires a widget name. For example:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate widget\nUsage: cli generate widget <SuperdataWidget>\n\nopenc3-cosmos-gse % openc3.sh cli generate widget HelloworldWidget\nWidget HelloworldWidget successfully generated!\nPlease be sure HelloworldWidget does not overlap an existing widget: https://docs.openc3.com/docs/configuration/telemetry-screens\n"})}),"\n",(0,i.jsx)(t.p,{children:"This creates the following files and directories:"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"Name"}),(0,i.jsx)(t.th,{children:"Description"})]})}),(0,i.jsx)(t.tbody,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"src/HelloworldWidget.vue"}),(0,i.jsx)(t.td,{children:"Fully functional widget which displays a simple value. This can be expanded using existing COSMOS Vue.js code to create any data visualization imaginable."})]})})]}),"\n",(0,i.jsx)(t.p,{children:"It also updates the plugin.txt file to add the new widget:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ruby",children:"WIDGET Helloworld\n"})}),"\n",(0,i.jsx)(t.h2,{id:"tool-generator",children:"Tool Generator"}),"\n",(0,i.jsxs)(t.p,{children:["The tool generator creates the scaffolding for a new COSMOS Tool. It's It must operate inside an existing COSMOS plugin and requires a tool name. Developing a custom tool requires intensive knowledge of a Javascript framework such as Vue.js, Angular, React, or Svelte. Since all the COSMOS tools are built in Vue.js, that is the recommended framework for new tool development. For additional help on frontend development, see ",(0,i.jsx)(t.a,{href:"../development/developing#running-a-frontend-application",children:"Running a Frontend Application"}),"."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"openc3-cosmos-gse % openc3.sh cli generate tool\nUsage: cli generate tool 'Tool Name'\n\nopenc3-cosmos-gse % openc3.sh cli generate widget DataVis\nTool datavis successfully generated!\nPlease be sure datavis does not conflict with any other tools\n"})}),"\n",(0,i.jsx)(t.p,{children:"This creates the following files and directories:"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"Name"}),(0,i.jsx)(t.th,{children:"Description"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"src/App.vue"}),(0,i.jsx)(t.td,{children:"Basic Vue template to render the application."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"src/main.js"}),(0,i.jsx)(t.td,{children:"Entry point for the new tool which loads Vue, Vuetify, and other libraries."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"src/router.js"}),(0,i.jsx)(t.td,{children:"Vue component router."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"src/tools/datavis"}),(0,i.jsx)(t.td,{children:"Contains all the files necessary to serve a web-based tool named datavis. The name is always defined in all lowercase. Due to technical limitations, the toolname must be unique and cannot be renamed at installation."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"src/tools/datavis/datavis.vue"}),(0,i.jsx)(t.td,{children:"Fully functional tool which displays a simple button. This can be expanded using existing COSMOS Vue.js code to create any tool imaginable."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"package.json"}),(0,i.jsx)(t.td,{children:"Build and dependency definition file. Used by npm or yarn to build the tool."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"vue.config.js"}),(0,i.jsx)(t.td,{children:"Vue configuration file used to serve the application in development and build the application."})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"<dotfiles>"}),(0,i.jsx)(t.td,{children:"Various dotfiles which help configure formatters and tools for Javascript frontend development"})]})]})]}),"\n",(0,i.jsxs)(t.p,{children:["It also updates the plugin.txt file to add the new tool. The icon can be changed to any of the material design icons found ",(0,i.jsx)(t.a,{href:"https://pictogrammers.com/library/mdi/",children:"here"}),"."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-ruby",children:'TOOL datavis "DataVis"\n INLINE_URL main.js\n ICON mdi-file-cad-box\n'})})]})}function h(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},2840:function(e,t,n){n.d(t,{Z:function(){return a},a:function(){return o}});var s=n(2784);let i={},r=s.createContext(i);function o(e){let t=s.useContext(r);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([["602"],{8747:function(e,n,i){i.r(n),i.d(n,{default:()=>d,frontMatter:()=>r,metadata:()=>t,assets:()=>l,toc:()=>a,contentTitle:()=>c});var t=JSON.parse('{"id":"development/curl","title":"Testing with Curl","description":"How to use Curl to hit the COSMOS APIs","source":"@site/docs/development/curl.md","sourceDirName":"development","slug":"/development/curl","permalink":"/tools/staticdocs/docs/development/curl","draft":false,"unlisted":false,"editUrl":"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/development/curl.md","tags":[],"version":"current","frontMatter":{"title":"Testing with Curl","description":"How to use Curl to hit the COSMOS APIs","sidebar_custom_props":{"myEmoji":"\uD83C\uDF0A"}},"sidebar":"defaultSidebar","previous":{"title":"Development","permalink":"/tools/staticdocs/docs/development"},"next":{"title":"Developing COSMOS","permalink":"/tools/staticdocs/docs/development/developing"}}'),s=i("2322"),o=i("2840");let r={title:"Testing with Curl",description:"How to use Curl to hit the COSMOS APIs",sidebar_custom_props:{myEmoji:"\uD83C\uDF0A"}},c=void 0,l={},a=[{value:"Curl Example with OpenC3 COSMOS Core",id:"curl-example-with-openc3-cosmos-core",level:2},{value:"Curl Example with OpenC3 COSMOS Enterprise",id:"curl-example-with-openc3-cosmos-enterprise",level:2},{value:"Suite Runner Example",id:"suite-runner-example",level:2}];function p(e){let n={admonition:"admonition",code:"code",h2:"h2",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.admonition,{title:"This documentation is for COSMOS Developers",type:"note",children:(0,s.jsx)(n.p,{children:"This information is just generally used behind the scenes in COSMOS tools"})}),"\n",(0,s.jsx)(n.p,{children:"The COSMOS APIs are all served over HTTP, which means you can use curl to experiment with them. Curl is a great tool for seeing exactly how the API responds to any given request."}),"\n",(0,s.jsx)(n.h2,{id:"curl-example-with-openc3-cosmos-core",children:"Curl Example with OpenC3 COSMOS Core"}),"\n",(0,s.jsx)(n.p,{children:"OpenC3 COSMOS Core just has a single user account, so all you need to do is pass the single password as the token with your requests like this."}),"\n",(0,s.jsx)(n.p,{children:"Request:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'curl -i -H "Content-Type: application/json-rpc" -H "Authorization: password" -d \'{"jsonrpc": "2.0", "method": "tlm", "params": ["INST HEALTH_STATUS TEMP1"], "keyword_params": {"scope": "DEFAULT"}, "id": 8}\' -X POST http://127.0.0.1:2900/openc3-api/api\n'})}),"\n",(0,s.jsx)(n.p,{children:"Response:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'HTTP/1.1 200 OK\nCache-Control: max-age=0, private, must-revalidate\nContent-Length: 51\nContent-Type: application/json-rpc\nEtag: W/"e806aacfdbed0b325e7a5928e3bb5cf4"\nVary: Origin\nX-Request-Id: bbad6c6b-6d22-4374-a86f-b5b0b95e6939\nX-Runtime: 0.059044\nDate: Sat, 04 Nov 2023 21:34:47 GMT\n\n{"jsonrpc":"2.0","id":8,"result":53.26555000000001}\n'})}),"\n",(0,s.jsx)(n.h2,{id:"curl-example-with-openc3-cosmos-enterprise",children:"Curl Example with OpenC3 COSMOS Enterprise"}),"\n",(0,s.jsx)(n.p,{children:"OpenC3 COSMOS Enterprise uses the Keycloak Single Sign-on system, so you must first request a token from Keycloak using a username and password pair, before you make requests. By default this token will expire in 5 minutes, and will need to be refreshed if it expires before your next request."}),"\n",(0,s.jsx)(n.p,{children:"Keycloak Request:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"# Get tokens from Keycloak - You will need to update the username and password with your account\ncurl -i -H \"Content-Type: application/x-www-form-urlencoded\" -d 'username=operator&password=operator&client_id=api&grant_type=password&scope=openid' -X POST http://127.0.0.1:2900/auth/realms/openc3/protocol/openid-connect/token\n"})}),"\n",(0,s.jsx)(n.p,{children:"Keycloak Response:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'HTTP/1.1 200 OK\nCache-Control: no-store\nContent-Length: 3207\nContent-Type: application/json\nPragma: no-cache\nReferrer-Policy: no-referrer\nSet-Cookie: KEYCLOAK_LOCALE=; Version=1; Comment=Expiring cookie; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0; Path=/auth/realms/openc3/; HttpOnly\nSet-Cookie: KC_RESTART=; Version=1; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0; Path=/auth/realms/openc3/; HttpOnly\nStrict-Transport-Security: max-age=31536000; includeSubDomains\nX-Content-Type-Options: nosniff\nX-Frame-Options: SAMEORIGIN\nX-Xss-Protection: 1; mode=block\nDate: Wed, 10 May 2023 00:40:40 GMT\n\n{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ0cDlERmpNZGFXMy16WXptdlBqVTZnNTVqMVNhWGhkZHJqU0szQVNvaDhVIn0.eyJleHAiOjE2ODM2Nzk1NDAsImlhdCI6MTY4MzY3OTI0MCwianRpIjoiZmVlOTQwYWYtZDY3Ny00MWUyLWIzNWYtZDI5ODhiM2RhZGQ2IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDoyOTAwL2F1dGgvcmVhbG1zL29wZW5jMyIsInN1YiI6ImFjZTFlNmExLTkzMTktNDc2ZS1iZjQzLTZmM2NhYjllZTJkZSIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFwaSIsInNlc3Npb25fc3RhdGUiOiJmMzc4NTk2Ny0yYTQ2LTRjMTItYWQwYy1jZmY3ZmM0NzdkZjkiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtb3BlbmMzIiwiQUxMU0NPUEVTX19vcGVyYXRvciIsIm9mZmxpbmVfYWNjZXNzIiwiQUxMU0NPUEVTX192aWV3ZXIiXX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJmMzc4NTk2Ny0yYTQ2LTRjMTItYWQwYy1jZmY3ZmM0NzdkZjkiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJUaGUgT3BlcmF0b3IiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJvcGVyYXRvciIsImdpdmVuX25hbWUiOiJUaGUiLCJmYW1pbHlfbmFtZSI6Ik9wZXJhdG9yIn0.eSqSeZrmCTahwltz5jsu5r3w6W15T5h0BvIdqKWQBDcnxAcxKuT-Nwziw_ewySSgHeC172CIWJUpHVp8ACDQG-dfW4KkvA6AcGfSF_f8TBH_rZrVQwlvwwzdA_egGKzhZWcnAC8TDjXRxuaWmnOgWT0aaHZAoW8EvwmKp-1IVz2l0B-hqzfC7dkjMrCI1udLfDvDBza9OtuR-FnKGt8h4nYnRzr8pO2jwebPFyZlR00gVsyK-b411XqprpT-qpRObYZwH5womA-8xIiwRZj9dsfQ1TaHGFkp1LNzxcj_r6pfwVO263bohbeU7ImezQdbvGLJ9NHaglzVNroTui4BXA","expires_in":300,"refresh_expires_in":1800,"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI5NjNlMjJiMS0wZmYwLTRmZjktYTg0Zi1hOGI4MzcxOWFiMDEifQ.eyJleHAiOjE2ODM2ODEwNDAsImlhdCI6MTY4MzY3OTI0MCwianRpIjoiMmQyYjIyNmItNjJkOS00YjRjLWI3YTYtMGEwYjk4MGQyMjMwIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDoyOTAwL2F1dGgvcmVhbG1zL29wZW5jMyIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6MjkwMC9hdXRoL3JlYWxtcy9vcGVuYzMiLCJzdWIiOiJhY2UxZTZhMS05MzE5LTQ3NmUtYmY0My02ZjNjYWI5ZWUyZGUiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiYXBpIiwic2Vzc2lvbl9zdGF0ZSI6ImYzNzg1OTY3LTJhNDYtNGMxMi1hZDBjLWNmZjdmYzQ3N2RmOSIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJmMzc4NTk2Ny0yYTQ2LTRjMTItYWQwYy1jZmY3ZmM0NzdkZjkifQ.1HlKdxQkaL5tYuHTXsOceLZFmNNLl9BjoA4oUl70x9M","token_type":"Bearer","id_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ0cDlERmpNZGFXMy16WXptdlBqVTZnNTVqMVNhWGhkZHJqU0szQVNvaDhVIn0.eyJleHAiOjE2ODM2Nzk1NDAsImlhdCI6MTY4MzY3OTI0MCwiYXV0aF90aW1lIjowLCJqdGkiOiJhNDJkOTY1ZS1lMzU0LTRiM2QtOTIyYS1hOWE0ZDgwZWYxMTkiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjI5MDAvYXV0aC9yZWFsbXMvb3BlbmMzIiwiYXVkIjoiYXBpIiwic3ViIjoiYWNlMWU2YTEtOTMxOS00NzZlLWJmNDMtNmYzY2FiOWVlMmRlIiwidHlwIjoiSUQiLCJhenAiOiJhcGkiLCJzZXNzaW9uX3N0YXRlIjoiZjM3ODU5NjctMmE0Ni00YzEyLWFkMGMtY2ZmN2ZjNDc3ZGY5IiwiYXRfaGFzaCI6IjNBWE9ISkFKYzFPVldLd2Y0a0Q4TkEiLCJhY3IiOiIxIiwic2lkIjoiZjM3ODU5NjctMmE0Ni00YzEyLWFkMGMtY2ZmN2ZjNDc3ZGY5IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiVGhlIE9wZXJhdG9yIiwicHJlZmVycmVkX3VzZXJuYW1lIjoib3BlcmF0b3IiLCJnaXZlbl9uYW1lIjoiVGhlIiwiZmFtaWx5X25hbWUiOiJPcGVyYXRvciJ9.gdLl6KOKIIAdl6jYEuAXQrGCNvuwLQb3RDnwrHJdqyFXshiwofBiLMFreRsIE-33xXWNBU6pnSLQHPVlQU5Vmzlk0IOfk-b4yNq0dNa1TV1kmnxRl8w1ulTQYVZjdsN-oyLNwe0v3aJcYtbvIA3DP8rgO6bVv0ogkjWtlda6MbkyZN-har8x3raUVSlUPRP2Basy1xSMNNA1jvB-nEM-aubrUZE6r0PjI6PE1hbLPmuPbcX3uuIwXu2-UoXepkB8H7omUuMm-S98aHpRarwszC0mmHD5b_wiXusMVw4xYw8eavFue4zfw-T2IKuTVtxbMTygXIah6iqi4gkpL8Mx1w","not-before-policy":0,"session_state":"f3785967-2a46-4c12-ad0c-cff7fc477df9","scope":"openid profile email"}\n'})}),"\n",(0,s.jsx)(n.p,{children:"COSMOS Request:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'# COSMOS Request now looks like this:\n\ncurl -i -H "Content-Type: application/json-rpc" -H "Authorization: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ0cDlERmpNZGFXMy16WXptdlBqVTZnNTVqMVNhWGhkZHJqU0szQVNvaDhVIn0.eyJleHAiOjE2ODM2Nzk1NDAsImlhdCI6MTY4MzY3OTI0MCwianRpIjoiZmVlOTQwYWYtZDY3Ny00MWUyLWIzNWYtZDI5ODhiM2RhZGQ2IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDoyOTAwL2F1dGgvcmVhbG1zL29wZW5jMyIsInN1YiI6ImFjZTFlNmExLTkzMTktNDc2ZS1iZjQzLTZmM2NhYjllZTJkZSIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFwaSIsInNlc3Npb25fc3RhdGUiOiJmMzc4NTk2Ny0yYTQ2LTRjMTItYWQwYy1jZmY3ZmM0NzdkZjkiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtb3BlbmMzIiwiQUxMU0NPUEVTX19vcGVyYXRvciIsIm9mZmxpbmVfYWNjZXNzIiwiQUxMU0NPUEVTX192aWV3ZXIiXX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJmMzc4NTk2Ny0yYTQ2LTRjMTItYWQwYy1jZmY3ZmM0NzdkZjkiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJUaGUgT3BlcmF0b3IiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJvcGVyYXRvciIsImdpdmVuX25hbWUiOiJUaGUiLCJmYW1pbHlfbmFtZSI6Ik9wZXJhdG9yIn0.eSqSeZrmCTahwltz5jsu5r3w6W15T5h0BvIdqKWQBDcnxAcxKuT-Nwziw_ewySSgHeC172CIWJUpHVp8ACDQG-dfW4KkvA6AcGfSF_f8TBH_rZrVQwlvwwzdA_egGKzhZWcnAC8TDjXRxuaWmnOgWT0aaHZAoW8EvwmKp-1IVz2l0B-hqzfC7dkjMrCI1udLfDvDBza9OtuR-FnKGt8h4nYnRzr8pO2jwebPFyZlR00gVsyK-b411XqprpT-qpRObYZwH5womA-8xIiwRZj9dsfQ1TaHGFkp1LNzxcj_r6pfwVO263bohbeU7ImezQdbvGLJ9NHaglzVNroTui4BXA" -d \'{"jsonrpc": "2.0", "method": "tlm", "params": ["INST HEALTH_STATUS TEMP1"], "keyword_params": {"scope": "DEFAULT"}, "id": 8}\' -X POST http://127.0.0.1:2900/openc3-api/api\n'})}),"\n",(0,s.jsx)(n.p,{children:"COSMOS Response:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'HTTP/1.1 200 OK\nCache-Control: max-age=0, private, must-revalidate\nContent-Type: application/json-rpc\nEtag: W/"1e44c0878528687014e1e60a1cbebdae"\nVary: Origin\nX-Request-Id: 47a8dd26-1348-4693-8df1-5375f60abc6c\nX-Runtime: 0.046477\nDate: Wed, 10 May 2023 00:41:33 GMT\nTransfer-Encoding: chunked\n\n{"jsonrpc":"2.0","id":8,"result":29.204100000000007}\n'})}),"\n",(0,s.jsx)(n.h2,{id:"suite-runner-example",children:"Suite Runner Example"}),"\n",(0,s.jsxs)(n.p,{children:["It can be very useful to run the a suite or script remotely from a continuous testing server. COSMOS' REST API allows for this. To figure out what is required to run a certain task on the web GUI you can open up your browser's developer tools to monitor the network traffic. You will see all the requests and responses required to run a command and you can reformat them yourself to suit your own purposes. Below is an example of running a test script from a Chromium-based browser:\n",(0,s.jsx)(n.img,{src:"https://github.com/OpenC3/cosmos/assets/55999897/df642d42-43e0-47f9-9b52-d42746d9746b",alt:"Network Traffic in browser developer tools"})]}),"\n",(0,s.jsxs)(n.p,{children:['You can see that there are 5 transactions total. To investigate just right-click on the network transaction and click "copy as ',(0,s.jsx)(n.code,{children:"curl"}),'" (depends on the browser). Here is an example of the second one:']}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"curl 'http://localhost:2900/script-api/scripts/TARGET/procedures/cmd_tlm_test.rb/lock?scope=DEFAULT' \\\n -X 'POST' \\\n -H 'Accept: application/json' \\\n -H 'Accept-Language: en-US,en;q=0.9' \\\n -H 'Authorization: pass' \\\n -H 'Connection: keep-alive' \\\n -H 'Content-Length: 0' \\\n -H 'Origin: http://ascportal:2900' \\\n -H 'Referer: http://localhost:2900/tools/scriptrunner/?file=TARGET%2Fprocedures%2Fcmd_tlm_test.rb' \\\n -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0' \\\n --insecure\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Many of the browser-specific headers are not required. The important thing to notice here is the URL and the request (in this case ",(0,s.jsx)(n.code,{children:"POST"}),"). If we inspect all of these we'll find out what each one does:"]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Set the script contents","\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"this updates any local changes)"}),"\n",(0,s.jsxs)(n.li,{children:["Note that this is a different request to ",(0,s.jsx)(n.code,{children:"GET"})," the script contents. This is done on the page load."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:"Lock the script (so other users can't edit it during execution)"}),"\n",(0,s.jsx)(n.li,{children:"Run script (this takes a JSON with options)"}),"\n",(0,s.jsx)(n.li,{children:"Open Websocket for logs"}),"\n",(0,s.jsx)(n.li,{children:"Request Result (this URL is a little different because the results are saved in redis)"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Below is a bash script which does all the above given some options. It requires ",(0,s.jsx)(n.code,{children:"curl"})," for the web requests and ",(0,s.jsx)(n.code,{children:"jq"})," for JSON parsing and formatting. It locks and runs the script, continually checks its status, then requests the result."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'#!/bin/bash\nset -e\nTARGET=${1:-\'TARGET\'}\nSCRIPT=${2:-\'procedures/cmd_tlm_test.rb\'}\nSUITE=${3:-\'TestSuite\'}\nCOSMOS_HOST=\'http://localhost:2900\'\nSCRIPT_API="$COSMOS_HOST/script-api"\nSCRIPT_PATH="scripts/$TARGET/$SCRIPT"\nCURL_ARGS=(\n -H \'Accept: application/json\'\n -H \'Authorization: password\'\n -H \'Accept-Language: en-US,en;q=0.9\'\n -H \'Connection: keep-alive\'\n -H \'Content-Type: application/json\'\n --insecure\n --silent )\n\n# Lock script #\ncurl "$SCRIPT_API/$SCRIPT_PATH/lock?scope=DEFAULT" -X "POST" "${CURL_ARGS[@]}"\n\n# Run script #\nRUN_OPTS=$(cat <<-json\n{\n "environment": [],\n "suiteRunner": {\n "method": "start",\n "suite": "$SUITE",\n "options": [\n "continueAfterError"\n ]\n }\n}\njson\n)\nRUN_OPTS=$(<<<"$RUN_OPTS" jq -rc .)\nID=$(curl "$SCRIPT_API/$SCRIPT_PATH/run?scope=DEFAULT" --data-raw "$RUN_OPTS" "${CURL_ARGS[@]}")\n\necho "Starting Script \'$SCRIPT_PATH\' at $(date) (may take up to 15 minutes)" > /dev/stderr\necho "You can monitor it in Script Runner here: $COSMOS_HOST/tools/scriptrunner/$ID" > /dev/stderr\n# Loop while Script ID is still running #\nwhile true; do\n SCRIPT_STATUS="$(curl "$SCRIPT_API/running-script?scope=DEFAULT" "${CURL_ARGS[@]}" | jq ".[]|select(.id==$ID)")"\n if [[ -z $SCRIPT_STATUS ]]; then\n break;\n fi\n sleep 2\ndone\n\n# Request results #\nBUCKET_FILE_URI="$(curl "$SCRIPT_API/completed-scripts?scope=DEFAULT" "${CURL_ARGS[@]}" |\\\n jq \'[.[]|select(.name | test("\'"${SCRIPT_PATH#scripts/}"\' "))][0] | .log | @uri\' -r)"\n\nURL="$(curl "$COSMOS_HOST/openc3-api/storage/download/$BUCKET_FILE_URI?bucket=OPENC3_LOGS_BUCKET&scope=DEFAULT" "${CURL_ARGS[@]}" |jq .url -r)"\n\ncurl "$COSMOS_HOST$URL" "${CURL_ARGS[@]}"\n'})})]})}function d(e={}){let{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(p,{...e})}):p(e)}},2840:function(e,n,i){i.d(n,{Z:function(){return c},a:function(){return r}});var t=i(2784);let s={},o=t.createContext(s);function r(e){let n=t.useContext(o);return t.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([["3522"],{5865:function(e,n,s){s.r(n),s.d(n,{default:()=>d,frontMatter:()=>l,metadata:()=>o,assets:()=>a,toc:()=>c,contentTitle:()=>r});var o=JSON.parse('{"id":"meta/licenses","title":"Licenses","description":"COSMOS licenses including the AGPLv3 vs Commercial","source":"@site/docs/meta/licenses.md","sourceDirName":"meta","slug":"/meta/licenses","permalink":"/tools/staticdocs/docs/meta/licenses","draft":false,"unlisted":false,"editUrl":"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/meta/licenses.md","tags":[],"version":"current","frontMatter":{"title":"Licenses","description":"COSMOS licenses including the AGPLv3 vs Commercial","sidebar_custom_props":{"myEmoji":"\uD83D\uDD75\uFE0F"}},"sidebar":"defaultSidebar","previous":{"title":"Contributing","permalink":"/tools/staticdocs/docs/meta/contributing"},"next":{"title":"Philosophy","permalink":"/tools/staticdocs/docs/meta/philosophy"}}'),i=s("2322"),t=s("2840");let l={title:"Licenses",description:"COSMOS licenses including the AGPLv3 vs Commercial",sidebar_custom_props:{myEmoji:"\uD83D\uDD75\uFE0F"}},r=void 0,a={},c=[{value:"AGPLv3",id:"agplv3",level:2},{value:"Evaluation and Education Use Only",id:"evaluation-and-education-use-only",level:2},{value:"Commercial License",id:"commercial-license",level:2},{value:"Why you should buy a Commercial License",id:"why-you-should-buy-a-commercial-license",level:3},{value:"FAQs",id:"faqs",level:2}];function h(e){let n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"OpenC3 COSMOS is offered under a tri-licensing model allowing users to choose between the following three options:"}),"\n",(0,i.jsx)(n.h2,{id:"agplv3",children:"AGPLv3"}),"\n",(0,i.jsxs)(n.p,{children:["This is our default open source license and the license that most free users use. The AGPLv3 is a modification of the GPLv3 which is what is known as a copy-left license or a viral license. You can read the whole thing here: ",(0,i.jsx)(n.a,{href:"https://github.com/OpenC3/cosmos/blob/main/LICENSE.txt",children:"OpenC3 AGPLv3"})]}),"\n",(0,i.jsx)(n.p,{children:"Obviously, the actual license text applies, but here is a short summary:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The AGPL allows users to use the code however they want: For business, personal, etc., as long as they follow the other terms:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Users are anyone who could access the web-app. On the public internet, that is the whole world. On a private network, it is anyone with access to that network."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The software is provided as-is, no warranty"}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Users must be given access to all the source code and are also allowed to use it however they want under the same terms of the AGPLv3. This includes any modifications made, anything added, and all plugins."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"For web applications (like COSMOS), a link must be provided to all of the source code."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"There are some key implications of the above:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"You cannot keep anything proprietary from your users. They have the rights to take the code (and configuration) and do anything they want with it. You CANNOT impede these rights or you are violating the AGPLv3 and YOU lose the rights to use our software."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"You must provide a digital link to all source code for your users, including plugins."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"All plugins must be licensed in an AGPLv3 compatible fashion. We recommend the MIT license because that allows your plugins to be compatible with the AGPLv3 and our commercial license. You can also use a dual license similar to what we do indicating the AGPLv3 or a purchased OpenC3 Commercial license."}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The AGPLv3 license is often chosen because it works well for open core products like COSMOS. Competitors cannot take the open source product and license it under different terms. They would be forever locked into the AGPLv3 which is difficult to monetize, because your customers can take any code you provide and publish it on the internet for free use by everyone."}),"\n",(0,i.jsx)(n.p,{children:"As the copyright holder, OpenC3 is able to license the product and derivatives commercially. No-one else can do this. (OpenC3 is also able to license legacy Ball Aerospace COSMOS code under IP agreement)"}),"\n",(0,i.jsx)(n.h2,{id:"evaluation-and-education-use-only",children:"Evaluation and Education Use Only"}),"\n",(0,i.jsxs)(n.p,{children:["This license takes effect as soon as you use any plugin we publish under Evaluation and Education terms. Currently the only plugin we use for this is our CCSDS CFDP plugin: ",(0,i.jsx)(n.a,{href:"https://github.com/OpenC3/openc3-cosmos-cfdp",children:"CFDP Plugin"})]}),"\n",(0,i.jsx)(n.p,{children:"You can read the whole license here:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'# OpenC3 Evaluation and Educational License\n#\n# Copyright 2023 OpenC3, Inc.\n#\n# This work is licensed for evaluation and educational purposes only.\n# It may NOT be used for formal development, integration and test, operations\n# or any other commercial purpose without the purchase of a commercial license\n# from OpenC3, Inc.\n#\n# The above copyright notice and this permission notice shall be included in all copies\n# or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\n# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n'})}),"\n",(0,i.jsx)(n.p,{children:"This license is pretty straight forward, but the key is you can't use this code for any real work leading to a product (Formal Development, Integration and Test, or Operations) unless you switch to purchasing a commercial license."}),"\n",(0,i.jsx)(n.h2,{id:"commercial-license",children:"Commercial License"}),"\n",(0,i.jsx)(n.p,{children:"This license is a signed contract with OpenC3. It allows use of our code for a program under contractual terms where you do not have to follow the AGPLv3."}),"\n",(0,i.jsx)(n.p,{children:"Generally we license to a specific project with terms that allow for unlimited users, and installs as needed by that project. Any code and plugins that you develop under the commercial license can be kept proprietary."}),"\n",(0,i.jsx)(n.p,{children:"These licenses are sold as yearly subscriptions, or as a non-expiring perpetual license. We also offer site licenses, and licenses to support unlimited missions on a government framework architecture."}),"\n",(0,i.jsx)(n.p,{children:"Of course with our commercial license, you also get all the extra functionality of our Enterprise product."}),"\n",(0,i.jsx)(n.h3,{id:"why-you-should-buy-a-commercial-license",children:"Why you should buy a Commercial License"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"You want to save years and tens of millions of dollars developing the same functionality yourself."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"You want all of the Enterprise functionality of COSMOS Enterprise"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"User Accounts"}),"\n",(0,i.jsx)(n.li,{children:"Role Based Access Control"}),"\n",(0,i.jsx)(n.li,{children:"LDAP Support"}),"\n",(0,i.jsx)(n.li,{children:"Kubernetes Support"}),"\n",(0,i.jsx)(n.li,{children:"Cloud Deployment Configurations"}),"\n",(0,i.jsx)(n.li,{children:"The right to use CFDP and other Enterprise Only plugins"}),"\n",(0,i.jsx)(n.li,{children:"Grafana Support"}),"\n",(0,i.jsx)(n.li,{children:"Support from the COSMOS Developers"}),"\n",(0,i.jsxs)(n.li,{children:["Lots more - See our ",(0,i.jsx)(n.a,{href:"https://openc3.com/enterprise",children:"Enterprise"})," page"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"You don't want to follow the AGPLv3"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"You want to keep the code and plugins you develop proprietary"}),"\n",(0,i.jsx)(n.li,{children:"You don't want to publish an accessible link to your source code"}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"You want to support the continued development and innovation of the COSMOS product"}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.em,{children:"We appreciate all of our commercial customers. You make OpenC3 possible. Thank you."})})}),"\n",(0,i.jsx)(n.h2,{id:"faqs",children:"FAQs"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"I see both Ball Aerospace & Technologies Corp as well as OpenC3, Inc in the copyright headers. What does this mean?"}),"\n",(0,i.jsx)(n.p,{children:"OpenC3, Inc has an intellectual property agreement with BAE (formerly Ball Aerospace & Technologies Corp) which gives us the rights to commercialize the original work that we built at Ball Aerospace. Customers only need to purchase a commercial license from OpenC3."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"What are the limits of the COSMOS Enterprise? How many users can we have? How many times can it be installed?"}),"\n",(0,i.jsx)(n.p,{children:"The COSMOS Enterprise license has no user or installation limits."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"How is the COSMOS Enterprise license enforced?"}),"\n",(0,i.jsx)(n.p,{children:"The COSMOS Enterprise license is enforced through contract only without license managers or additional software controls."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"How is the COSMOS Enterprise license applied? Per company? Per program?"}),"\n",(0,i.jsxs)(n.p,{children:["COSMOS Enterprise is typically licensed to a named mission or group. We also have site licenses, company licenses, and mission ops center licenses. Please contact us at ",(0,i.jsx)(n.a,{href:"mailto:sales@openc3.com",children:"sales@openc3.com"})," for more information."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Do you license to foreign companies? How do you handle ITAR or the EAR?"}),"\n",(0,i.jsxs)(n.p,{children:["We have several international customers and are not subject to ITAR export controls. We are export controlled under the EAR via ECCN 5D002c1. We have a detailed writeup explaining this justification as well as a commodity classification document from the Department of Commerce. Please contact us at ",(0,i.jsx)(n.a,{href:"mailto:sales@openc3.com",children:"sales@openc3.com"})," for more information."]}),"\n"]}),"\n"]})]})}function d(e={}){let{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},2840:function(e,n,s){s.d(n,{Z:function(){return r},a:function(){return l}});var o=s(2784);let i={},t=o.createContext(i);function l(e){let n=o.useContext(t);return o.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:l(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([["3927"],{929:function(e,r,n){n.r(r),n.d(r,{default:()=>o,frontMatter:()=>l,metadata:()=>i,assets:()=>c,toc:()=>h,contentTitle:()=>d});var i=JSON.parse('{"id":"configuration/plugins","title":"Plugins","description":"Plugin definition file format and keywords","source":"@site/docs/configuration/plugins.md","sourceDirName":"configuration","slug":"/configuration/plugins","permalink":"/tools/staticdocs/docs/configuration/plugins","draft":false,"unlisted":false,"editUrl":"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/configuration/plugins.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"sidebar_position":2,"title":"Plugins","description":"Plugin definition file format and keywords","sidebar_custom_props":{"myEmoji":"\uD83D\uDD0C"}},"sidebar":"defaultSidebar","previous":{"title":"File Format","permalink":"/tools/staticdocs/docs/configuration/format"},"next":{"title":"Targets","permalink":"/tools/staticdocs/docs/configuration/target"}}'),s=n("2322"),t=n("2840");let l={sidebar_position:2,title:"Plugins",description:"Plugin definition file format and keywords",sidebar_custom_props:{myEmoji:"\uD83D\uDD0C"}},d=void 0,c={},h=[{value:"Introduction",id:"introduction",level:2},{value:"Concepts",id:"concepts",level:2},{value:"Target",id:"target",level:3},{value:"Interface",id:"interface",level:3},{value:"Router",id:"router",level:3},{value:"Tool",id:"tool",level:3},{value:"Microservice",id:"microservice",level:3},{value:"Plugin Directory Structure",id:"plugin-directory-structure",level:2},{value:"plugin.txt Configuration File",id:"plugintxt-configuration-file",level:2},{value:"VARIABLE",id:"variable",level:2},{value:"NEEDS_DEPENDENCIES",id:"needs_dependencies",level:2},{value:"INTERFACE",id:"interface-1",level:2},{value:"INTERFACE Modifiers",id:"interface-modifiers",level:2},{value:"MAP_TARGET",id:"map_target",level:3},{value:"MAP_CMD_TARGET",id:"map_cmd_target",level:3},{value:"MAP_TLM_TARGET",id:"map_tlm_target",level:3},{value:"DONT_CONNECT",id:"dont_connect",level:3},{value:"DONT_RECONNECT",id:"dont_reconnect",level:3},{value:"RECONNECT_DELAY",id:"reconnect_delay",level:3},{value:"DISABLE_DISCONNECT",id:"disable_disconnect",level:3},{value:"LOG_RAW",id:"log_raw",level:3},{value:"LOG_STREAM",id:"log_stream",level:3},{value:"PROTOCOL",id:"protocol",level:3},{value:"OPTION",id:"option",level:3},{value:"SECRET",id:"secret",level:3},{value:"ENV",id:"env",level:3},{value:"WORK_DIR",id:"work_dir",level:3},{value:"PORT",id:"port",level:3},{value:"CMD",id:"cmd",level:3},{value:"CONTAINER",id:"container",level:3},{value:"ROUTE_PREFIX",id:"route_prefix",level:3},{value:"SHARD",id:"shard",level:3},{value:"ROUTER",id:"router-1",level:2},{value:"TARGET",id:"target-1",level:2},{value:"TARGET Modifiers",id:"target-modifiers",level:2},{value:"CMD_BUFFER_DEPTH",id:"cmd_buffer_depth",level:3},{value:"CMD_LOG_CYCLE_TIME",id:"cmd_log_cycle_time",level:3},{value:"CMD_LOG_CYCLE_SIZE",id:"cmd_log_cycle_size",level:3},{value:"CMD_LOG_RETAIN_TIME",id:"cmd_log_retain_time",level:3},{value:"CMD_DECOM_LOG_CYCLE_TIME",id:"cmd_decom_log_cycle_time",level:3},{value:"CMD_DECOM_LOG_CYCLE_SIZE",id:"cmd_decom_log_cycle_size",level:3},{value:"CMD_DECOM_LOG_RETAIN_TIME",id:"cmd_decom_log_retain_time",level:3},{value:"TLM_BUFFER_DEPTH",id:"tlm_buffer_depth",level:3},{value:"TLM_LOG_CYCLE_TIME",id:"tlm_log_cycle_time",level:3},{value:"TLM_LOG_CYCLE_SIZE",id:"tlm_log_cycle_size",level:3},{value:"TLM_LOG_RETAIN_TIME",id:"tlm_log_retain_time",level:3},{value:"TLM_DECOM_LOG_CYCLE_TIME",id:"tlm_decom_log_cycle_time",level:3},{value:"TLM_DECOM_LOG_CYCLE_SIZE",id:"tlm_decom_log_cycle_size",level:3},{value:"TLM_DECOM_LOG_RETAIN_TIME",id:"tlm_decom_log_retain_time",level:3},{value:"REDUCED_MINUTE_LOG_RETAIN_TIME",id:"reduced_minute_log_retain_time",level:3},{value:"REDUCED_HOUR_LOG_RETAIN_TIME",id:"reduced_hour_log_retain_time",level:3},{value:"REDUCED_DAY_LOG_RETAIN_TIME",id:"reduced_day_log_retain_time",level:3},{value:"LOG_RETAIN_TIME",id:"log_retain_time",level:3},{value:"REDUCED_LOG_RETAIN_TIME",id:"reduced_log_retain_time",level:3},{value:"CLEANUP_POLL_TIME",id:"cleanup_poll_time",level:3},{value:"REDUCER_DISABLE",id:"reducer_disable",level:3},{value:"REDUCER_MAX_CPU_UTILIZATION",id:"reducer_max_cpu_utilization",level:3},{value:"TARGET_MICROSERVICE",id:"target_microservice",level:3},{value:"PACKET",id:"packet",level:3},{value:"DISABLE_ERB",id:"disable_erb",level:3},{value:"SHARD",id:"shard-1",level:3},{value:"MICROSERVICE",id:"microservice-1",level:2},{value:"MICROSERVICE Modifiers",id:"microservice-modifiers",level:2},{value:"ENV",id:"env-1",level:3},{value:"WORK_DIR",id:"work_dir-1",level:3},{value:"PORT",id:"port-1",level:3},{value:"TOPIC",id:"topic",level:3},{value:"TARGET_NAME",id:"target_name",level:3},{value:"CMD",id:"cmd-1",level:3},{value:"OPTION",id:"option-1",level:3},{value:"CONTAINER",id:"container-1",level:3},{value:"SECRET",id:"secret-1",level:3},{value:"ROUTE_PREFIX",id:"route_prefix-1",level:3},{value:"DISABLE_ERB",id:"disable_erb-1",level:3},{value:"SHARD",id:"shard-2",level:3},{value:"STOPPED",id:"stopped",level:3},{value:"TOOL",id:"tool-1",level:2},{value:"TOOL Modifiers",id:"tool-modifiers",level:2},{value:"URL",id:"url",level:3},{value:"INLINE_URL",id:"inline_url",level:3},{value:"WINDOW",id:"window",level:3},{value:"ICON",id:"icon",level:3},{value:"CATEGORY",id:"category",level:3},{value:"SHOWN",id:"shown",level:3},{value:"POSITION",id:"position",level:3},{value:"DISABLE_ERB",id:"disable_erb-2",level:3},{value:"IMPORT_MAP_ITEM",id:"import_map_item",level:3},{value:"WIDGET",id:"widget",level:2},{value:"WIDGET Modifiers",id:"widget-modifiers",level:2},{value:"DISABLE_ERB",id:"disable_erb-3",level:3}];function a(e){let r={a:"a",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(r.h2,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsx)(r.p,{children:"This document provides the information necessary to configure a COSMOS plugin. Plugins are how you configure and extend COSMOS."}),"\n",(0,s.jsx)(r.p,{children:"Plugins are where you define targets (and their corresponding command and telemetry packet definitions), where you configure the interfaces needed to talk to targets, where you can define routers to stream raw data out of COSMOS, how you can add new tools to the COSMOS user interface, and how you can run additional microservices to provide new functionality."}),"\n",(0,s.jsx)(r.p,{children:"Each plugin is built as a Ruby gem and thus has a plugin.gemspec file which builds it. Plugins have a plugin.txt file which declares all the variables used by the plugin and how to interface to the target(s) it contains."}),"\n",(0,s.jsx)(r.h2,{id:"concepts",children:"Concepts"}),"\n",(0,s.jsx)(r.h3,{id:"target",children:"Target"}),"\n",(0,s.jsx)(r.p,{children:"Targets are the external pieces of hardware and/or software that COSMOS communicates with. These are things like Front End Processors (FEPs), ground support equipment (GSE), custom software tools, and pieces of hardware like satellites themselves. A target is anything that COSMOS can send commands to and receive telemetry from."}),"\n",(0,s.jsx)(r.h3,{id:"interface",children:"Interface"}),"\n",(0,s.jsx)(r.p,{children:"Interfaces implement the physical connection to one or more targets. They are typically ethernet connections implemented using TCP or UDP but can be other connections like serial ports. Interfaces send commands to targets and receive telemetry from targets."}),"\n",(0,s.jsx)(r.h3,{id:"router",children:"Router"}),"\n",(0,s.jsx)(r.p,{children:"Routers flow streams of telemetry packets out of COSMOS and receive streams of commands into COSMOS. The commands are forwarded by COSMOS to associated interfaces. Telemetry comes from associated interfaces."}),"\n",(0,s.jsx)(r.h3,{id:"tool",children:"Tool"}),"\n",(0,s.jsx)(r.p,{children:"COSMOS Tools are web-based applications the communicate with the COSMOS APIs to perform takes like displaying telemetry, sending commands, and running scripts."}),"\n",(0,s.jsx)(r.h3,{id:"microservice",children:"Microservice"}),"\n",(0,s.jsx)(r.p,{children:"Microservices are persistent running backend code that runs within the COSMOS environment. They can process data and perform other useful tasks."}),"\n",(0,s.jsx)(r.h2,{id:"plugin-directory-structure",children:"Plugin Directory Structure"}),"\n",(0,s.jsxs)(r.p,{children:["COSMOS plugins have a well-defined directory structure described in detail in the ",(0,s.jsx)(r.a,{href:"../getting-started/generators",children:"Code Generator"})," documentation."]}),"\n",(0,s.jsx)(r.h2,{id:"plugintxt-configuration-file",children:"plugin.txt Configuration File"}),"\n",(0,s.jsx)(r.p,{children:"A plugin.txt configuration file is required for any COSMOS plugin. It declares the contents of the plugin and provides variables that allow the plugin to be configured at the time it is initially installed or upgraded.\nThis file follows the standard COSMOS configuration file format of keywords followed by zero or more space separated parameters. The following keywords are supported by the plugin.txt config file:"}),"\n",(0,s.jsx)(r.h2,{id:"variable",children:"VARIABLE"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Define a configurable variable for the plugin"})}),"\n",(0,s.jsx)(r.p,{children:"The VARIABLE keyword defines a variable that will be requested for the user to enter during plugin installation. Variables can be used to handle details of targets that are user defined such as specific IP addresses and ports. Variables should also be used to allow users to rename targets to whatever name they want and support multiple installations of the same target with different names. Variables can be used later in plugin.txt or in any other configuration file included in a plugin using Ruby ERB syntax. The variables are assigned to accessible local variables in the file. At a high level, ERB allows you to run Ruby code in configuration files."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Variable Name"}),(0,s.jsx)(r.td,{children:"The name of the variable"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Default Value"}),(0,s.jsx)(r.td,{children:"Default value of the variable"}),(0,s.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,s.jsx)(r.h2,{id:"needs_dependencies",children:"NEEDS_DEPENDENCIES"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.5.0)"}),(0,s.jsx)(r.strong,{children:"Indicates the plugin needs dependencies and sets the GEM_HOME environment variable"})]}),"\n",(0,s.jsx)(r.p,{children:"If the plugin has a top level lib folder or lists runtime dependencies in the gemspec, NEEDS_DEPENDENCIES is effectively already set. Note that in Enterprise, having NEEDS_DEPENDENCIES adds the NFS volume mount to the Kubernetes pod."}),"\n",(0,s.jsx)(r.h2,{id:"interface-1",children:"INTERFACE"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Defines a connection to a physical target"})}),"\n",(0,s.jsx)(r.p,{children:"Interfaces are what OpenC3 uses to talk to a particular piece of hardware. Interfaces require a Ruby or Python file which implements all the interface methods necessary to talk to the hardware. OpenC3 defines many built in interfaces or you can define your own as long as it implements the interface protocol."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Interface Name"}),(0,s.jsx)(r.td,{children:"Name of the interface. This name will appear in the Interfaces tab of the Server and is also referenced by other keywords. The OpenC3 convention is to name interfaces after their targets with '_INT' appended to the name, e.g. INST_INT for the INST target."}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Filename"}),(0,s.jsxs)(r.td,{children:["Ruby or Python file to use when instantiating the interface.",(0,s.jsx)("br",{}),(0,s.jsx)("br",{}),"Valid Values: ",(0,s.jsx)("span",{class:"values",children:"tcpip_client_interface, tcpip_server_interface, udp_interface, serial_interface"})]}),(0,s.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,s.jsxs)(r.p,{children:["Additional parameters are required. Please see the ",(0,s.jsx)(r.a,{href:"/tools/staticdocs/docs/configuration/interfaces",children:"Interfaces"})," documentation for more details."]}),"\n",(0,s.jsx)(r.h2,{id:"interface-modifiers",children:"INTERFACE Modifiers"}),"\n",(0,s.jsx)(r.p,{children:"The following keywords must follow a INTERFACE keyword."}),"\n",(0,s.jsx)(r.h3,{id:"map_target",children:"MAP_TARGET"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Maps a target name to an interface"})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Target Name"}),(0,s.jsx)(r.td,{children:"Target name to map to this interface"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"INTERFACE DATA_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET DATA\n"})}),"\n",(0,s.jsx)(r.p,{children:"Python Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-python",children:"INTERFACE DATA_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET DATA\n"})}),"\n",(0,s.jsx)(r.h3,{id:"map_cmd_target",children:"MAP_CMD_TARGET"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,s.jsx)(r.strong,{children:"Maps a target name to an interface for commands only"})]}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Target Name"}),(0,s.jsx)(r.td,{children:"Command target name to map to this interface"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"INTERFACE CMD_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_CMD_TARGET DATA # Only DATA commands go on the CMD_INT interface\n"})}),"\n",(0,s.jsx)(r.p,{children:"Python Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-python",children:"INTERFACE CMD_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_CMD_TARGET DATA # Only DATA commands go on the CMD_INT interface\n"})}),"\n",(0,s.jsx)(r.h3,{id:"map_tlm_target",children:"MAP_TLM_TARGET"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,s.jsx)(r.strong,{children:"Maps a target name to an interface for telemetry only"})]}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Target Name"}),(0,s.jsx)(r.td,{children:"Telemetry target name to map to this interface"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"INTERFACE TLM_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TLM_TARGET DATA # Only DATA telemetry received on TLM_INT interface\n"})}),"\n",(0,s.jsx)(r.p,{children:"Python Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-python",children:"INTERFACE TLM_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TLM_TARGET DATA # Only DATA telemetry received on TLM_INT interface\n"})}),"\n",(0,s.jsx)(r.h3,{id:"dont_connect",children:"DONT_CONNECT"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Server will not automatically try to connect to the interface at startup"})}),"\n",(0,s.jsx)(r.h3,{id:"dont_reconnect",children:"DONT_RECONNECT"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Server will not try to reconnect to the interface if the connection is lost"})}),"\n",(0,s.jsx)(r.h3,{id:"reconnect_delay",children:"RECONNECT_DELAY"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Reconnect delay in seconds"})}),"\n",(0,s.jsx)(r.p,{children:"If DONT_RECONNECT is not present the Server will try to reconnect to an interface if the connection is lost. Reconnect delay sets the interval in seconds between reconnect tries."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Delay"}),(0,s.jsx)(r.td,{children:"Delay in seconds between reconnect attempts. The default is 15 seconds."}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"disable_disconnect",children:"DISABLE_DISCONNECT"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Disable the Disconnect button on the Interfaces tab in the Server"})}),"\n",(0,s.jsx)(r.p,{children:"Use this keyword to prevent the user from disconnecting from the interface. This is typically used in a 'production' environment where you would not want the user to inadvertently disconnect from a target."}),"\n",(0,s.jsx)(r.h3,{id:"log_raw",children:"LOG_RAW"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Deprecated, use LOG_STREAM"})}),"\n",(0,s.jsx)(r.h3,{id:"log_stream",children:"LOG_STREAM"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.5.2)"}),(0,s.jsx)(r.strong,{children:"Log all data on the interface exactly as it is sent and received"})]}),"\n",(0,s.jsx)(r.p,{children:"LOG_STREAM does not add any OpenC3 headers and thus can not be read by OpenC3 tools. It is primarily useful for low level debugging of an interface. You will have to manually parse these logs yourself using a hex editor or other application."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Cycle Time"}),(0,s.jsx)(r.td,{children:"Amount of time to wait before cycling the log file. Default is 10 min. If nil refer to Cycle Hour and Cycle Minute."}),(0,s.jsx)(r.td,{children:"False"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Cycle Size"}),(0,s.jsx)(r.td,{children:"Amount of data to write before cycling the log file. Default is 50MB."}),(0,s.jsx)(r.td,{children:"False"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Cycle Hour"}),(0,s.jsx)(r.td,{children:"The time at which to cycle the log. Combined with Cycle Minute to cycle the log daily at the specified time. If nil, the log will be cycled hourly at the specified Cycle Minute. Only applies if Cycle Time is nil."}),(0,s.jsx)(r.td,{children:"False"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Cycle Minute"}),(0,s.jsx)(r.td,{children:"See Cycle Hour."}),(0,s.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"INTERFACE EXAMPLE example_interface.rb\n # Override the default log time of 600\n LOG_STREAM 60\n"})}),"\n",(0,s.jsx)(r.h3,{id:"protocol",children:"PROTOCOL"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 4.0.0)"}),(0,s.jsx)(r.strong,{children:"Protocols modify the interface by processing the data"})]}),"\n",(0,s.jsxs)(r.p,{children:["Protocols can be either READ, WRITE, or READ_WRITE. READ protocols act on the data received by the interface while write acts on the data before it is sent out. READ_WRITE applies the protocol to both reading and writing.",(0,s.jsx)("br",{}),(0,s.jsx)("br",{})," For information on creating your own custom protocol please see ",(0,s.jsx)(r.a,{href:"/tools/staticdocs/docs/configuration/protocols",children:"Protocols"})]}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Type"}),(0,s.jsxs)(r.td,{children:["Whether to apply the protocol on incoming data, outgoing data, or both",(0,s.jsx)("br",{}),(0,s.jsx)("br",{}),"Valid Values: ",(0,s.jsx)("span",{class:"values",children:"READ, WRITE, READ_WRITE"})]}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Protocol Filename or Classname"}),(0,s.jsx)(r.td,{children:"Ruby or Python filename or class name which implements the protocol"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Protocol specific parameters"}),(0,s.jsx)(r.td,{children:"Additional parameters used by the protocol"}),(0,s.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"INTERFACE DATA_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil nil\n MAP_TARGET DATA\n # Rather than defining the LENGTH protocol on the INTERFACE line we define it here\n PROTOCOL READ LengthProtocol 0 16 0 1 BIG_ENDIAN 4 0xBA5EBA11\n"})}),"\n",(0,s.jsx)(r.p,{children:"Python Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-python",children:"INTERFACE DATA_INT openc3/interfaces/tcpip_client_interface.py host.docker.internal 8080 8081 10.0 nil BURST\n MAP_TARGET DATA\n PROTOCOL READ IgnorePacketProtocol INST IMAGE # Drop all INST IMAGE packets\n"})}),"\n",(0,s.jsx)(r.h3,{id:"option",children:"OPTION"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Set a parameter on an interface"})}),"\n",(0,s.jsx)(r.p,{children:"When an option is set the interface class calls the set_option method. Custom interfaces can override set_option to handle any additional options they want."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Name"}),(0,s.jsx)(r.td,{children:"The option to set. OpenC3 defines several options on the core provided interfaces. The SerialInterface defines FLOW_CONTROL which can be NONE (default) or RTSCTS and DATA_BITS which changes the data bits of the serial interface. The TcpipServerInterface and HttpServerInterface define LISTEN_ADDRESS which is the IP address to accept connections on (default 0.0.0.0)."}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Parameters"}),(0,s.jsx)(r.td,{children:"Parameters to pass to the option"}),(0,s.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"INTERFACE SERIAL_INT serial_interface.rb COM1 COM1 115200 NONE 1 10.0 nil\n OPTION FLOW_CONTROL RTSCTS\n OPTION DATA_BITS 8\nROUTER SERIAL_ROUTER tcpip_server_interface.rb 2950 2950 10.0 nil BURST\n ROUTE SERIAL_INT\n OPTION LISTEN_ADDRESS 127.0.0.1\n"})}),"\n",(0,s.jsx)(r.h3,{id:"secret",children:"SECRET"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.3.0)"}),(0,s.jsx)(r.strong,{children:"Define a secret needed by this interface"})]}),"\n",(0,s.jsxs)(r.p,{children:["Defines a secret for this interface and optionally assigns its value to an option. For more information see ",(0,s.jsx)(r.a,{href:"/docs/tools/admin#secrets",children:"Admin Secrets"}),"."]}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Type"}),(0,s.jsx)(r.td,{children:"ENV or FILE. ENV will mount the secret into an environment variable. FILE mounts the secret into a file."}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Secret Name"}),(0,s.jsxs)(r.td,{children:["The name of the secret to retrieve from the Admin / Secrets tab. For more information see ",(0,s.jsx)(r.a,{href:"/docs/tools/admin#secrets",children:"Admin Secrets"}),"."]}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Environment Variable or File Path"}),(0,s.jsx)(r.td,{children:"Environment variable name or file path to store secret. Note that if you use the Option Name to set an option to the secret value, this value doesn't really matter as long as it is unique."}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Option Name"}),(0,s.jsx)(r.td,{children:"Interface option to pass the secret value. This is the primary way to pass secrets to interfaces."}),(0,s.jsx)(r.td,{children:"False"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Secret Store Name"}),(0,s.jsx)(r.td,{children:"Name of the secret store for stores with multipart keys"}),(0,s.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:'SECRET ENV USERNAME ENV_USERNAME USERNAME\nSECRET FILE KEY "/tmp/DATA/cert" KEY\n'})}),"\n",(0,s.jsx)(r.h3,{id:"env",children:"ENV"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,s.jsx)(r.strong,{children:"Sets an environment variable in the microservice."})]}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Key"}),(0,s.jsx)(r.td,{children:"Environment variable name"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Value"}),(0,s.jsx)(r.td,{children:"Environment variable value"}),(0,s.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"ENV COMPANY OpenC3\n"})}),"\n",(0,s.jsx)(r.h3,{id:"work_dir",children:"WORK_DIR"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,s.jsx)(r.strong,{children:"Set the working directory"})]}),"\n",(0,s.jsx)(r.p,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Directory"}),(0,s.jsx)(r.td,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"WORK_DIR '/openc3/lib/openc3/microservices'\n"})}),"\n",(0,s.jsx)(r.h3,{id:"port",children:"PORT"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,s.jsx)(r.strong,{children:"Open port for the microservice"})]}),"\n",(0,s.jsx)(r.p,{children:"Kubernetes needs a Service to be applied to open a port so this is required for Kubernetes support"}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Number"}),(0,s.jsx)(r.td,{children:"Port number"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Protocol"}),(0,s.jsx)(r.td,{children:"Port protocol. Default is TCP."}),(0,s.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"PORT 7272\n"})}),"\n",(0,s.jsx)(r.h3,{id:"cmd",children:"CMD"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,s.jsx)(r.strong,{children:"Command line to execute to run the microservice."})]}),"\n",(0,s.jsx)(r.p,{children:"Command line to execute to run the microservice."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Args"}),(0,s.jsx)(r.td,{children:"One or more arguments to exec to run the microservice."}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"CMD ruby interface_microservice.rb DEFAULT__INTERFACE__INT1\n"})}),"\n",(0,s.jsx)(r.p,{children:"Python Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-python",children:"CMD python interface_microservice.py DEFAULT__INTERFACE__INT1\n"})}),"\n",(0,s.jsx)(r.h3,{id:"container",children:"CONTAINER"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,s.jsx)(r.strong,{children:"Docker Container"})]}),"\n",(0,s.jsx)(r.p,{children:"Container to execute and run the microservice in. Only used in COSMOS Enterprise."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Args"}),(0,s.jsx)(r.td,{children:"Name of the container"}),(0,s.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"route_prefix",children:"ROUTE_PREFIX"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.7.0)"}),(0,s.jsx)(r.strong,{children:"Prefix of route"})]}),"\n",(0,s.jsx)(r.p,{children:"Prefix of route to the microservice to expose externally with Traefik"}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Route Prefix"}),(0,s.jsx)(r.td,{children:"Route prefix. Must be unique across all scopes. Something like /myprefix"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"ROUTE_PREFIX /interface\n"})}),"\n",(0,s.jsx)(r.h3,{id:"shard",children:"SHARD"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 6.0.0)"}),(0,s.jsx)(r.strong,{children:"Operator shard to run target microservices on"})]}),"\n",(0,s.jsx)(r.p,{children:"Operator Shard. Only used if running multiple operator containers typically in Kubernetes"}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Shard"}),(0,s.jsx)(r.td,{children:"Shard number starting from 0"}),(0,s.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"SHARD 0\n"})}),"\n",(0,s.jsx)(r.h2,{id:"router-1",children:"ROUTER"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Create router to receive commands and output telemetry packets from one or more interfaces"})}),"\n",(0,s.jsx)(r.p,{children:"Creates an router which receives command packets from their remote clients and sends them to associated interfaces. They receive telemetry packets from their interfaces and send them to their remote clients. This allows routers to be intermediaries between an external client and an actual device."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Name"}),(0,s.jsx)(r.td,{children:"Name of the router"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Filename"}),(0,s.jsxs)(r.td,{children:["Ruby or Python file to use when instantiating the interface.",(0,s.jsx)("br",{}),(0,s.jsx)("br",{}),"Valid Values: ",(0,s.jsx)("span",{class:"values",children:"tcpip_client_interface, tcpip_server_interface, udp_interface, serial_interface"})]}),(0,s.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,s.jsxs)(r.p,{children:["Additional parameters are required. Please see the ",(0,s.jsx)(r.a,{href:"/tools/staticdocs/docs/configuration/interfaces",children:"Interfaces"})," documentation for more details."]}),"\n",(0,s.jsx)(r.h2,{id:"target-1",children:"TARGET"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Defines a new target"})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Folder Name"}),(0,s.jsx)(r.td,{children:"The target folder"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Name"}),(0,s.jsx)(r.td,{children:"The target name. While this is almost always the same as Folder Name it can be different to create multiple targets based on the same target folder."}),(0,s.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"TARGET INST INST\n"})}),"\n",(0,s.jsx)(r.h2,{id:"target-modifiers",children:"TARGET Modifiers"}),"\n",(0,s.jsx)(r.p,{children:"The following keywords must follow a TARGET keyword."}),"\n",(0,s.jsx)(r.h3,{id:"cmd_buffer_depth",children:"CMD_BUFFER_DEPTH"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,s.jsx)(r.strong,{children:"Number of commands to buffer to ensure logged in order"})]}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Buffer Depth"}),(0,s.jsx)(r.td,{children:"Buffer depth in packets (Default = 5)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"cmd_log_cycle_time",children:"CMD_LOG_CYCLE_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Command binary logs can be cycled on a time interval."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"cmd_log_cycle_size",children:"CMD_LOG_CYCLE_SIZE"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Command binary logs can be cycled after a certain log file size is reached."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Size"}),(0,s.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"cmd_log_retain_time",children:"CMD_LOG_RETAIN_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"How long to keep raw command logs in seconds."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Number of seconds to keep raw command logs (default = nil = Forever)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"cmd_decom_log_cycle_time",children:"CMD_DECOM_LOG_CYCLE_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Command decommutation logs can be cycled on a time interval."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"cmd_decom_log_cycle_size",children:"CMD_DECOM_LOG_CYCLE_SIZE"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Command decommutation logs can be cycled after a certain log file size is reached."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Size"}),(0,s.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"cmd_decom_log_retain_time",children:"CMD_DECOM_LOG_RETAIN_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"How long to keep decom command logs in seconds."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Number of seconds to keep decom command logs (default = nil = Forever)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"tlm_buffer_depth",children:"TLM_BUFFER_DEPTH"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,s.jsx)(r.strong,{children:"Number of telemetry packets to buffer to ensure logged in order"})]}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Buffer Depth"}),(0,s.jsx)(r.td,{children:"Buffer depth in packets (Default = 60)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"tlm_log_cycle_time",children:"TLM_LOG_CYCLE_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Telemetry binary logs can be cycled on a time interval."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"tlm_log_cycle_size",children:"TLM_LOG_CYCLE_SIZE"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Telemetry binary logs can be cycled after a certain log file size is reached."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Size"}),(0,s.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"tlm_log_retain_time",children:"TLM_LOG_RETAIN_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"How long to keep raw telemetry logs in seconds."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Number of seconds to keep raw telemetry logs (default = nil = Forever)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"tlm_decom_log_cycle_time",children:"TLM_DECOM_LOG_CYCLE_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Telemetry decommutation logs can be cycled on a time interval."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Maximum time between files in seconds (default = 600)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"tlm_decom_log_cycle_size",children:"TLM_DECOM_LOG_CYCLE_SIZE"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Telemetry decommutation logs can be cycled after a certain log file size is reached."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Size"}),(0,s.jsx)(r.td,{children:"Maximum file size in bytes (default = 50_000_000)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"tlm_decom_log_retain_time",children:"TLM_DECOM_LOG_RETAIN_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"How long to keep decom telemetry logs in seconds."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Number of seconds to keep decom telemetry logs (default = nil = Forever)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"reduced_minute_log_retain_time",children:"REDUCED_MINUTE_LOG_RETAIN_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"How long to keep reduced minute telemetry logs in seconds."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Number of seconds to keep reduced minute telemetry logs (default = nil = Forever)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"reduced_hour_log_retain_time",children:"REDUCED_HOUR_LOG_RETAIN_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"How long to keep reduced hour telemetry logs in seconds."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Number of seconds to keep reduced hour telemetry logs (default = nil = Forever)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"reduced_day_log_retain_time",children:"REDUCED_DAY_LOG_RETAIN_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"How long to keep reduced day telemetry logs in seconds."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Number of seconds to keep reduced day telemetry logs (default = nil = Forever)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"log_retain_time",children:"LOG_RETAIN_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"How long to keep all regular telemetry logs in seconds."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Number of seconds to keep all regular telemetry logs (default = nil = Forever)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"reduced_log_retain_time",children:"REDUCED_LOG_RETAIN_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"How long to keep all reduced telemetry logs in seconds."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Number of seconds to keep all reduced telemetry logs (default = nil = Forever)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"cleanup_poll_time",children:"CLEANUP_POLL_TIME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Period at which to run the cleanup process."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Time"}),(0,s.jsx)(r.td,{children:"Number of seconds between runs of the cleanup process (default = 600 = 10 minutes)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"reducer_disable",children:"REDUCER_DISABLE"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Disables the data reduction microservice for the target"})}),"\n",(0,s.jsx)(r.h3,{id:"reducer_max_cpu_utilization",children:"REDUCER_MAX_CPU_UTILIZATION"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Maximum amount of CPU utilization to apply to data reduction"})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Percentage"}),(0,s.jsx)(r.td,{children:"0 to 100 percent (default = 30)"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"target_microservice",children:"TARGET_MICROSERVICE"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,s.jsx)(r.strong,{children:"Breaks a target microservice out into its own process."})]}),"\n",(0,s.jsx)(r.p,{children:"Can be used to give more resources to processing that is falling behind. If defined multiple times for the same type, will create multiple processes. Each process can be given specific packets to process with the PACKET keyword."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Type"}),(0,s.jsx)(r.td,{children:"The target microservice type. Must be one of DECOM, COMMANDLOG, DECOMCMDLOG, PACKETLOG, DECOMLOG, REDUCER, or CLEANUP"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"packet",children:"PACKET"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.2.0)"}),(0,s.jsx)(r.strong,{children:"Packet Name to allocate to the current TARGET_MICROSERVICE."})]}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Packet Name"}),(0,s.jsx)(r.td,{children:"The packet name. Does not apply to REDUCER or CLEANUP target microservice types."}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"disable_erb",children:"DISABLE_ERB"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,s.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,s.jsx)(r.p,{children:"Disable ERB processing for the entire target or a set of regular expressions over its filenames"}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Regex"}),(0,s.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,s.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"shard-1",children:"SHARD"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 6.0.0)"}),(0,s.jsx)(r.strong,{children:"Operator shard to run target microservices on"})]}),"\n",(0,s.jsx)(r.p,{children:"Operator Shard. Only used if running multiple operator containers typically in Kubernetes"}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Shard"}),(0,s.jsx)(r.td,{children:"Shard number starting from 0"}),(0,s.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"SHARD 0\n"})}),"\n",(0,s.jsx)(r.h2,{id:"microservice-1",children:"MICROSERVICE"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Defines a new microservice"})}),"\n",(0,s.jsx)(r.p,{children:"Defines a microservice that the plugin adds to the OpenC3 system. Microservices are background software processes that perform persistent processing."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Microservice Folder Name"}),(0,s.jsx)(r.td,{children:"The exact name of the microservice folder in the plugin. ie. microservices/MicroserviceFolderName"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Microservice Name"}),(0,s.jsx)(r.td,{children:"The specific name of this instance of the microservice in the OpenC3 system"}),(0,s.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n"})}),"\n",(0,s.jsx)(r.h2,{id:"microservice-modifiers",children:"MICROSERVICE Modifiers"}),"\n",(0,s.jsx)(r.p,{children:"The following keywords must follow a MICROSERVICE keyword."}),"\n",(0,s.jsx)(r.h3,{id:"env-1",children:"ENV"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Sets an environment variable in the microservice."})}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Key"}),(0,s.jsx)(r.td,{children:"Environment variable name"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Value"}),(0,s.jsx)(r.td,{children:"Environment variable value"}),(0,s.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n ENV COMPANY OpenC3\n"})}),"\n",(0,s.jsx)(r.h3,{id:"work_dir-1",children:"WORK_DIR"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Set the working directory"})}),"\n",(0,s.jsx)(r.p,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Directory"}),(0,s.jsx)(r.td,{children:"Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in."}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n WORK_DIR .\n"})}),"\n",(0,s.jsx)(r.h3,{id:"port-1",children:"PORT"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.0.10)"}),(0,s.jsx)(r.strong,{children:"Open port for the microservice"})]}),"\n",(0,s.jsx)(r.p,{children:"Kubernetes needs a Service to be applied to open a port so this is required for Kubernetes support"}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Number"}),(0,s.jsx)(r.td,{children:"Port number"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Protocol"}),(0,s.jsx)(r.td,{children:"Port protocol. Default is TCP."}),(0,s.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n PORT 7272\n"})}),"\n",(0,s.jsx)(r.h3,{id:"topic",children:"TOPIC"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Associate a Redis topic"})}),"\n",(0,s.jsx)(r.p,{children:"Redis topic to associate with this microservice. Standard OpenC3 microservices such as decom_microservice use this information to know what packet streams to subscribe to. The TOPIC keyword can be used as many times as necessary to associate all needed topics."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Topic Name"}),(0,s.jsx)(r.td,{children:"Redis Topic to associate with the microservice"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n # Manually assigning topics is an advanced topic and requires\n # intimate knowledge of the internal COSMOS data structures.\n TOPIC DEFAULT__openc3_log_messages\n TOPIC DEFAULT__TELEMETRY__EXAMPLE__STATUS\n"})}),"\n",(0,s.jsx)(r.h3,{id:"target_name",children:"TARGET_NAME"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Associate a OpenC3 target"})}),"\n",(0,s.jsx)(r.p,{children:"OpenC3 target to associate with the microservice. For standard OpenC3 microservices such as decom_microservice this causes the target configuration to get loaded into the container for the microservice."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Target Name"}),(0,s.jsx)(r.td,{children:"OpenC3 target to associate with the microservice"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n TARGET_NAME EXAMPLE\n"})}),"\n",(0,s.jsx)(r.h3,{id:"cmd-1",children:"CMD"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Command line to execute to run the microservice."})}),"\n",(0,s.jsx)(r.p,{children:"Command line to execute to run the microservice."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Args"}),(0,s.jsx)(r.td,{children:"One or more arguments to exec to run the microservice."}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Ruby Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE EXAMPLE openc3-example\n CMD ruby example_target.rb\n"})}),"\n",(0,s.jsx)(r.p,{children:"Python Example:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-python",children:"MICROSERVICE EXAMPLE openc3-example\n CMD python example_target.py\n"})}),"\n",(0,s.jsx)(r.h3,{id:"option-1",children:"OPTION"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Pass an option to the microservice"})}),"\n",(0,s.jsx)(r.p,{children:"Generic key/value(s) options to pass to the microservice. These take the form of KEYWORD/PARAMS like a line in a OpenC3 configuration file. Multiple OPTION keywords can be used to pass multiple options to the microservice."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Option Name"}),(0,s.jsx)(r.td,{children:"Name of the option"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Option Value(s)"}),(0,s.jsx)(r.td,{children:"One or more values to associate with the option"}),(0,s.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,s.jsx)(r.h3,{id:"container-1",children:"CONTAINER"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Docker Container"})}),"\n",(0,s.jsx)(r.p,{children:"Container to execute and run the microservice in. Only used in COSMOS Enterprise."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Args"}),(0,s.jsx)(r.td,{children:"Name of the container"}),(0,s.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"secret-1",children:"SECRET"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.3.0)"}),(0,s.jsx)(r.strong,{children:"Define a secret needed by this microservice"})]}),"\n",(0,s.jsxs)(r.p,{children:["Defines a secret for this microservice. For more information see ",(0,s.jsx)(r.a,{href:"/docs/tools/admin#secrets",children:"Admin Secrets"}),"."]}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Type"}),(0,s.jsx)(r.td,{children:"ENV or FILE. ENV will mount the secret into an environment variable. FILE mounts the secret into a file."}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Secret Name"}),(0,s.jsxs)(r.td,{children:["The name of the secret to retrieve from the Admin / Secrets tab. For more information see ",(0,s.jsx)(r.a,{href:"/docs/tools/admin#secrets",children:"Admin Secrets"}),"."]}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Environment Variable or File Path"}),(0,s.jsx)(r.td,{children:"Environment variable name or file path to store secret"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Secret Store Name"}),(0,s.jsx)(r.td,{children:"Name of the secret store for stores with multipart keys"}),(0,s.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:'SECRET ENV USERNAME ENV_USERNAME\nSECRET FILE KEY "/tmp/DATA/cert"\n'})}),"\n",(0,s.jsx)(r.h3,{id:"route_prefix-1",children:"ROUTE_PREFIX"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.5.0)"}),(0,s.jsx)(r.strong,{children:"Prefix of route"})]}),"\n",(0,s.jsx)(r.p,{children:"Prefix of route to the microservice to expose externally with Traefik"}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Route Prefix"}),(0,s.jsx)(r.td,{children:"Route prefix. Must be unique across all scopes. Something like /myprefix"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"MICROSERVICE CFDP CFDP\n ROUTE_PREFIX /cfdp\n"})}),"\n",(0,s.jsx)(r.h3,{id:"disable_erb-1",children:"DISABLE_ERB"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,s.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,s.jsx)(r.p,{children:"Disable ERB processing for the entire microservice or a set of regular expressions over its filenames"}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Regex"}),(0,s.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,s.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"shard-2",children:"SHARD"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 6.0.0)"}),(0,s.jsx)(r.strong,{children:"Operator shard to run target microservices on"})]}),"\n",(0,s.jsx)(r.p,{children:"Operator Shard. Only used if running multiple operator containers typically in Kubernetes"}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Shard"}),(0,s.jsx)(r.td,{children:"Shard number starting from 0"}),(0,s.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"SHARD 0\n"})}),"\n",(0,s.jsx)(r.h3,{id:"stopped",children:"STOPPED"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 6.2.0)"}),(0,s.jsx)(r.strong,{children:"Initially creates the microservice in a stopped state (not enabled)"})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"STOPPED\n"})}),"\n",(0,s.jsx)(r.h2,{id:"tool-1",children:"TOOL"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Define a tool"})}),"\n",(0,s.jsx)(r.p,{children:"Defines a tool that the plugin adds to the OpenC3 system. Tools are web based applications that make use of the Single-SPA javascript library that allows them to by dynamically added to the running system as independent frontend microservices."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Tool Folder Name"}),(0,s.jsx)(r.td,{children:"The exact name of the tool folder in the plugin. ie. tools/ToolFolderName"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Tool Name"}),(0,s.jsx)(r.td,{children:"Name of the tool that is displayed in the OpenC3 Navigation menu"}),(0,s.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"TOOL DEMO Demo\n"})}),"\n",(0,s.jsx)(r.h2,{id:"tool-modifiers",children:"TOOL Modifiers"}),"\n",(0,s.jsx)(r.p,{children:"The following keywords must follow a TOOL keyword."}),"\n",(0,s.jsx)(r.h3,{id:"url",children:"URL"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Url used to access the tool"})}),"\n",(0,s.jsx)(r.p,{children:'The relative url used to access the tool. Defaults to "/tools/ToolFolderName".'}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Url"}),(0,s.jsx)(r.td,{children:"The url. If not given defaults to tools/ToolFolderName. Generally should not be given unless linking to external tools."}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"inline_url",children:"INLINE_URL"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Internal url to load a tool"})}),"\n",(0,s.jsx)(r.p,{children:'The url of the javascript file used to load the tool into single-SPA. Defaults to "main.js".'}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Url"}),(0,s.jsx)(r.td,{children:"The inline url. If not given defaults to main.js. Generally should not be given unless using a non-standard filename."}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"window",children:"WINDOW"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"How to display the tool when navigated to"})}),"\n",(0,s.jsx)(r.p,{children:"The window mode used to display the tool. INLINE opens the tool internally without refreshing the page using the Single-SPA framework. IFRAME opens external tools in an Iframe within OpenC3. NEW opens the tool in a new TAB."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Window Mode"}),(0,s.jsxs)(r.td,{children:["Tool display mode",(0,s.jsx)("br",{}),(0,s.jsx)("br",{}),"Valid Values: ",(0,s.jsx)("span",{class:"values",children:"INLINE, IFRAME, NEW"})]}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"icon",children:"ICON"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Set tool icon"})}),"\n",(0,s.jsx)(r.p,{children:"Icon shown next to the tool name in the OpenC3 navigation menu."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Icon Name"}),(0,s.jsxs)(r.td,{children:["Icon to display next to the tool name. Icons come from Font Awesome, Material Design (",(0,s.jsx)(r.a,{href:"https://materialdesignicons.com/",children:"https://materialdesignicons.com/"}),"), and Astro."]}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"category",children:"CATEGORY"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Category for the tool"})}),"\n",(0,s.jsx)(r.p,{children:"Associates the tool with a category which becomes a submenu in the Navigation menu."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Category Name"}),(0,s.jsx)(r.td,{children:"Category to associate the tool with"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"shown",children:"SHOWN"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Show the tool or not"})}),"\n",(0,s.jsx)(r.p,{children:"Whether or not the tool is shown in the Navigation menu. Should generally be true, except for the openc3 base tool."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Shown"}),(0,s.jsxs)(r.td,{children:["Whether or not the tool is shown. TRUE or FALSE",(0,s.jsx)("br",{}),(0,s.jsx)("br",{}),"Valid Values: ",(0,s.jsx)("span",{class:"values",children:"true, false"})]}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"position",children:"POSITION"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.0.8)"}),(0,s.jsx)(r.strong,{children:"Position of the tool in the nav bar"})]}),"\n",(0,s.jsx)(r.p,{children:"Position of the tool starting at 2 (1 is reserved for Admin Console). Tools without a position are appended to the end as they are installed. All COSMOS Core tools have consecutive integer values for position."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Position"}),(0,s.jsx)(r.td,{children:"Numerical position"}),(0,s.jsx)(r.td,{children:"True"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"disable_erb-2",children:"DISABLE_ERB"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,s.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,s.jsx)(r.p,{children:"Disable ERB processing for the entire tool or a set of regular expressions over its filenames"}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Regex"}),(0,s.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,s.jsx)(r.td,{children:"False"})]})})]}),"\n",(0,s.jsx)(r.h3,{id:"import_map_item",children:"IMPORT_MAP_ITEM"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 6.0.0)"}),(0,s.jsx)(r.strong,{children:"Add an item to the import map"})]}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"key"}),(0,s.jsx)(r.td,{children:"Import Map Key"}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"value"}),(0,s.jsx)(r.td,{children:"Import Map Value"}),(0,s.jsx)(r.td,{children:"True"})]})]})]}),"\n",(0,s.jsx)(r.h2,{id:"widget",children:"WIDGET"}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.strong,{children:"Define a custom widget"})}),"\n",(0,s.jsx)(r.p,{children:"Defines a custom widget that can be used in Telemetry Viewer screens."}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsxs)(r.tbody,{children:[(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Widget Name"}),(0,s.jsxs)(r.td,{children:["The name of the widget will be used to build a path to the widget implementation. For example, ",(0,s.jsx)(r.code,{children:"WIDGET HELLOWORLD"})," will find the as-built file tools/widgets/HelloworldWidget/HelloworldWidget.umd.min.js. See the ",(0,s.jsx)(r.a,{href:"/tools/staticdocs/docs/guides/custom-widgets",children:"Custom Widgets"})," guide for more details."]}),(0,s.jsx)(r.td,{children:"True"})]}),(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Label"}),(0,s.jsx)(r.td,{children:"The label for the widget that will appear in the Data Viewer component drop down"}),(0,s.jsx)(r.td,{children:"False"})]})]})]}),"\n",(0,s.jsx)(r.p,{children:"Example Usage:"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-ruby",children:"WIDGET HELLOWORLD\n"})}),"\n",(0,s.jsx)(r.h2,{id:"widget-modifiers",children:"WIDGET Modifiers"}),"\n",(0,s.jsx)(r.p,{children:"The following keywords must follow a WIDGET keyword."}),"\n",(0,s.jsx)(r.h3,{id:"disable_erb-3",children:"DISABLE_ERB"}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)("div",{class:"right",children:"(Since 5.12.0)"}),(0,s.jsx)(r.strong,{children:"Disable ERB processing"})]}),"\n",(0,s.jsx)(r.p,{children:"Disable ERB processing for the entire widget or a set of regular expressions over its filenames"}),"\n",(0,s.jsxs)(r.table,{children:[(0,s.jsx)(r.thead,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.th,{children:"Parameter"}),(0,s.jsx)(r.th,{children:"Description"}),(0,s.jsx)(r.th,{children:"Required"})]})}),(0,s.jsx)(r.tbody,{children:(0,s.jsxs)(r.tr,{children:[(0,s.jsx)(r.td,{children:"Regex"}),(0,s.jsx)(r.td,{children:"Regex to match against filenames. If match, then no ERB processing"}),(0,s.jsx)(r.td,{children:"False"})]})})]})]})}function o(e={}){let{wrapper:r}={...(0,t.a)(),...e.components};return r?(0,s.jsx)(r,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},2840:function(e,r,n){n.d(r,{Z:function(){return d},a:function(){return l}});var i=n(2784);let s={},t=i.createContext(s);function l(e){let r=i.useContext(t);return i.useMemo(function(){return"function"==typeof e?e(r):{...r,...e}},[r,e])}function d(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),i.createElement(t.Provider,{value:r},e.children)}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([["9880"],{8198:function(e,t,i){i.r(t),i.d(t,{default:()=>d,frontMatter:()=>o,metadata:()=>n,assets:()=>c,toc:()=>l,contentTitle:()=>a});var n=JSON.parse('{"id":"configuration/ssl-tls","title":"SSL-TLS","description":"How to configure SSL and TLS","source":"@site/docs/configuration/ssl-tls.md","sourceDirName":"configuration","slug":"/configuration/ssl-tls","permalink":"/tools/staticdocs/docs/configuration/ssl-tls","draft":false,"unlisted":false,"editUrl":"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/configuration/ssl-tls.md","tags":[],"version":"current","sidebarPosition":11,"frontMatter":{"sidebar_position":11,"title":"SSL-TLS","description":"How to configure SSL and TLS","sidebar_custom_props":{"myEmoji":"\uD83D\uDD10"}},"sidebar":"defaultSidebar","previous":{"title":"Screens","permalink":"/tools/staticdocs/docs/configuration/telemetry-screens"},"next":{"title":"Tools","permalink":"/tools/staticdocs/docs/tools"}}'),r=i("2322"),s=i("2840");let o={sidebar_position:11,title:"SSL-TLS",description:"How to configure SSL and TLS",sidebar_custom_props:{myEmoji:"\uD83D\uDD10"}},a=void 0,c={},l=[{value:"Understanding SSL, TLS, and Public Key Infrastructure (PKI)",id:"understanding-ssl-tls-and-public-key-infrastructure-pki",level:2},{value:"Configure COSMOS for TLS",id:"configure-cosmos-for-tls",level:2},{value:"Obtain or Generate the Certificates",id:"obtain-or-generate-the-certificates",level:3},{value:"Configuring cacert.pem for your certificate authority",id:"configuring-cacertpem-for-your-certificate-authority",level:3},{value:"Configure COSMOS for TLS when running in Docker Compose",id:"configure-cosmos-for-tls-when-running-in-docker-compose",level:3},{value:"Enterprise Changes required for all TLS configurations",id:"enterprise-changes-required-for-all-tls-configurations",level:4},{value:"Using TLS and your own certificates",id:"using-tls-and-your-own-certificates",level:4},{value:"Using a global certificate from Let&#39;s Encrypt",id:"using-a-global-certificate-from-lets-encrypt",level:4},{value:"Configure COSMOS Enterprise for TLS when running in Kubernetes",id:"configure-cosmos-enterprise-for-tls-when-running-in-kubernetes",level:3}];function h(e){let t={a:"a",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["OpenC3 COSMOS is a container based service which does not use SSL/TLS out of the box. This guide will help you configure SSL and TLS. Learn more at the Traefik ",(0,r.jsx)(t.a,{href:"https://doc.traefik.io/traefik/routing/entrypoints/#tls",children:"docs"}),"."]}),"\n",(0,r.jsx)(t.h2,{id:"understanding-ssl-tls-and-public-key-infrastructure-pki",children:"Understanding SSL, TLS, and Public Key Infrastructure (PKI)"}),"\n",(0,r.jsx)(t.p,{children:"Security on the internet is built on the technologies SSL and TLS. SSL (Secure Sockets Layer) was the original version but is now an outdated technology that is no longer used in favor of the more modern TLS (Transport Layer Security). However, the terms SSL and TLS are still used interchangeably in most conversations. Public Key Infrastructure (PKI) is what makes secure sockets like SSL and TLS work - and is built around certificates, certificate authorities, and public key encryption."}),"\n",(0,r.jsx)(t.p,{children:'Public key encryption works with a set of two keys: the public key and the private key. A message encrypted with the public key can only be decrypted by the holder of the private key. This allows for secure messaging in one direction (from anyone with the public key to the single holder of the private key). Public keys can be safely shared "publicly" because they are only useful for creating an encrypted document that is useless to anyone without the private key. The private key should never be shared. Technically, the private key can also be used to encrypt messages that can be decrypted by the public key, but this is not useful since the public key is assumed to be available to everyone.'}),"\n",(0,r.jsx)(t.p,{children:"Certificate authorities issue certificates which contain a public key and additional information such as a domain name and are then digitally signed by the certificate authority. Verifying that the digital signature is valid (from a trusted certificate authority) is how your computer knows that if the public key works with a given domain name, then it can be trusted that the computer responding to that domain name is who it says it is. This can only be done if your computer has the information it needs to know if the certificate is valid. This information is included in the certificate authority trust store on your computer."}),"\n",(0,r.jsx)(t.p,{children:"Have you ever seen \"self signed certificate\" type error messages? These error messages mean that your computer's certificate authority trust store wasn't able to verify the signature on a certificate. Generally this is because the certificate was issued by a private certificate authority (like an Active Directory Server or other company specific issuer). Computers by default include the information they need to check certificates from major public issuers of certificates (like Let's Encrypt) but don't have any information on private issuers unless you set it up."}),"\n",(0,r.jsx)(t.p,{children:"Does this mean we can't use TLS without paying for certificates (or using free services like Let's Encrypt)? No, but it does mean if you use a private certificate authority, there is more work involved to make it work so that your computer will trust the certificates. This is unavoidable because computers are setup to not trust unknown certificate authorities for a good reason. If you trust all certificates then anyone can pretend to be any domain name on the internet. Side note: Domain Name Service (DNS) is still another layer of protection but TLS prevents someone who hacks DNS from also pretending to be valid domains."}),"\n",(0,r.jsx)(t.h2,{id:"configure-cosmos-for-tls",children:"Configure COSMOS for TLS"}),"\n",(0,r.jsx)(t.h3,{id:"obtain-or-generate-the-certificates",children:"Obtain or Generate the Certificates"}),"\n",(0,r.jsx)(t.p,{children:'Most OpenC3 customers will be using certificates generated by a private certificate authority. If your certificate authority is controlled by your IT department please contact them to receive the public key/private key and full certificate chain (cacert.pem) file for your domain name. Note that you must have the full certificate chain. Often CAs are "chained" with a root CA and one or more intermediate CAs. You must have the certificates for each in your cacert.pem or it will not work.'}),"\n",(0,r.jsx)(t.p,{children:"If using a cloud service, like AWS Private CA, follow the service's directions to retrieve these three files."}),"\n",(0,r.jsx)(t.p,{children:"If you are running COSMOS on an internet facing server (not recommended), then you can get free TLS certificates from Let's Encrypt. In this case the Traefik container will retrieve the certificates for you automatically (directions later on this page)."}),"\n",(0,r.jsx)(t.p,{children:"If you want to generate self-signed certificates, especially for an IP address rather than a domain name, we recommend using the mkcert utility."}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"Install mkcert (brew install mkcert on MacOs)"}),"\n",(0,r.jsx)(t.li,{children:"mkcert -install"}),"\n",(0,r.jsx)(t.li,{children:'mkcert "your ip or domain name here"'}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"This will generate YOURDOMAIN.pem (public key) and YOURDOMAIN-key.pem (private key)"}),"\n",(0,r.jsx)(t.h3,{id:"configuring-cacertpem-for-your-certificate-authority",children:"Configuring cacert.pem for your certificate authority"}),"\n",(0,r.jsxs)(t.p,{children:["If you are using certificates from a public certificate authority then you are good to go. We build all of our containers with a recent cacert.pem file that comes from the curl project and can be downloaded here: ",(0,r.jsx)(t.a,{href:"https://curl.se/ca/cacert.pem",children:"https://curl.se/ca/cacert.pem"}),". This file contains the information needed to verify certificates from all of the major public certificate authorities. You can safely skip ahead to configuring COSMOS with the TLS public/private keys."]}),"\n",(0,r.jsx)(t.p,{children:"However, if your certificates are coming from a private certificate authority then you will need to configure the COSMOS containers with a cacert.pem file that includes the necessary information from your private certificate authority. Note that all non-public certificate authorities will need to be configured including services like Amazon Private CA. COSMOS WILL NOT WORK WITHOUT FOLLOWING THIS STEP."}),"\n",(0,r.jsx)(t.p,{children:"It is recommended that you append your private certificate authority certificate to the end of the provided cacert.pem file. This allows COSMOS to work with the private CA and with the public internet over TLS."}),"\n",(0,r.jsx)(t.p,{children:"In general this can be done like this:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"cat myca.pem >> cacert.pem\n"})}),"\n",(0,r.jsx)(t.p,{children:"If using mkcert to create self signed certificates, this can be done as follows:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:'cat "`mkcert -CAROOT`"/rootCA.pem >> cacert.pem\n'})}),"\n",(0,r.jsx)(t.p,{children:"In all versions of COSMOS the base cacert.pem file can be found at the root of your COSMOS folder structure. This is the file you should modify/replace with your CA information."}),"\n",(0,r.jsx)(t.h3,{id:"configure-cosmos-for-tls-when-running-in-docker-compose",children:"Configure COSMOS for TLS when running in Docker Compose"}),"\n",(0,r.jsx)(t.p,{children:"Note: These instructions are only for Docker Compose (Both Core and Enterprise). If you are using Kubernetes with COSMOS Enterprise please see the Kubernetes instructions."}),"\n",(0,r.jsx)(t.p,{children:"Follow earlier instructions to obtain your private key, public key, and to modify cacert.pem as necessary."}),"\n",(0,r.jsx)(t.h4,{id:"enterprise-changes-required-for-all-tls-configurations",children:"Enterprise Changes required for all TLS configurations"}),"\n",(0,r.jsx)(t.p,{children:"If running COSMOS Core skip to the next section."}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsxs)(t.li,{children:["Edit compose.yaml","\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsxs)(t.li,{children:['Change this openc3-keycloak line: KC_HOSTNAME: "',(0,r.jsx)(t.a,{href:"http://localhost:2900/auth",children:"http://localhost:2900/auth"}),'"']}),"\n",(0,r.jsx)(t.li,{children:"It should be changed to the final url with correct http/https, domain, port and end with /auth"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["Edit .env","\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsxs)(t.li,{children:["Change the OPENC3_KEYCLOAK_EXTERNAL_URL and OPENC3_KEYCLOAK_URL lines so that ",(0,r.jsx)(t.strong,{children:"both"})," are set to the exact same url as set above in compose.yaml"]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["Edit openc3-enterprise-grafana/cosmos.yaml","\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"Change the cosmosUrl and keycloakUrl settings to the correct schema, domain, and port. Keep /auth if present."}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["Edit openc3-enterprise-grafana/grafana.ini","\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"Change the root_url, auth_url, token_url, and api_url settings to the correct schema, domain, and port, leave any additional path information."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(t.h4,{id:"using-tls-and-your-own-certificates",children:"Using TLS and your own certificates"}),"\n",(0,r.jsx)(t.p,{children:'The following steps are written for the enterprise folder names. Remove "-enterprise" for COSMOS Core.'}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"Copy your public SSL certificate to ./openc3-enterprise-traefik/cert.crt"}),"\n",(0,r.jsx)(t.li,{children:"Copy your private SSL certificate to ./openc3-enterprise-traefik/cert.key"}),"\n",(0,r.jsxs)(t.li,{children:["Edit compose.yaml","\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsxs)(t.li,{children:["Comment out this openc3-traefik line: ",(0,r.jsx)(t.code,{children:'- "./openc3-enterprise-traefik/traefik.yaml:/etc/traefik/traefik.yaml:z"'})]}),"\n",(0,r.jsxs)(t.li,{children:["Uncomment this openc3-traefik line: ",(0,r.jsx)(t.code,{children:'- "./openc3-enterprise-traefik/traefik-ssl.yaml:/etc/traefik/traefik.yaml"'})]}),"\n",(0,r.jsxs)(t.li,{children:["Uncomment this openc3-traefik line: ",(0,r.jsx)(t.code,{children:'- "./openc3-enterprise-traefik/cert.key:/etc/traefik/cert.key"'})]}),"\n",(0,r.jsxs)(t.li,{children:["Uncomment this openc3-traefik line: ",(0,r.jsx)(t.code,{children:'- "./openc3-enterprise-traefik/cert.crt:/etc/traefik/cert.crt"'})]}),"\n",(0,r.jsxs)(t.li,{children:["Modify this openc3-traefik line to remove the ip address and modify the first port number if desired ",(0,r.jsx)(t.strong,{children:"(Note: leave the last :2900)"}),": ",(0,r.jsx)(t.code,{children:'- "127.0.0.1:2900:2900"'})]}),"\n",(0,r.jsxs)(t.li,{children:["Modify this openc3-traefik line to remove the ip address and modify the first port number if desired ",(0,r.jsx)(t.strong,{children:"(Note: leave the last :2943)"}),": ",(0,r.jsx)(t.code,{children:'- "127.0.0.1:2943:2943"'})]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["Edit ./openc3-enterprise-traefik/traefik-ssl.yaml","\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:'Update line 22 to your domain: - main: "mydomain.com" # Update with your domain'}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["Start COSMOS","\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"On Linux/Mac: ./openc3.sh run"}),"\n",(0,r.jsx)(t.li,{children:"On Windows: openc3.bat run"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["Enterprise Only: After approximately 2 minutes, open a web browser to ",(0,r.jsx)(t.a,{href:"https://mydomain.com/auth/",children:"https://mydomain.com/auth/"}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:'If you run "docker ps", you can watch until the openc3-cosmos-enterprise-init container completes, at which point the system should be fully configured and ready to use.'}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["Enterprise Only: ",(0,r.jsx)(t.strong,{children:"IMPORTANT"}),": You must configure Keycloak before accessing ",(0,r.jsx)(t.a,{href:"https://mydomain.com",children:"https://mydomain.com"})," to get to the main COSMOS app and Grafana to work (you'll just see a solid color page until you do this) - Please follow the Keycloak documentation in our ",(0,r.jsx)(t.a,{href:"https://github.com/OpenC3/cosmos-enterprise/blob/main/docs/OpenC3%20COSMOS%20Enterprise%20Edition%20User's%20Manual.pdf",children:"User's Manual"})]}),"\n"]}),"\n",(0,r.jsx)(t.h4,{id:"using-a-global-certificate-from-lets-encrypt",children:"Using a global certificate from Let's Encrypt"}),"\n",(0,r.jsx)(t.p,{children:"Warning: These directions only work when exposing OpenC3 COSMOS to the internet. Make sure you understand the risks and have properly configured your server settings and firewall."}),"\n",(0,r.jsx)(t.p,{children:'The following steps are written for the enterprise folder names. Remove "-enterprise" for COSMOS Core.'}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"Make sure that your public DNS settings are mapping your domain name to your server"}),"\n",(0,r.jsxs)(t.li,{children:["Edit compose.yaml","\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsxs)(t.li,{children:["Comment out this openc3-traefik line: ",(0,r.jsx)(t.code,{children:'- "./openc3-enterprise-traefik/traefik.yaml:/etc/traefik/traefik.yaml:z"'})]}),"\n",(0,r.jsxs)(t.li,{children:["Uncomment this openc3-traefik line: ",(0,r.jsx)(t.code,{children:'- "./openc3-enterprise-traefik/traefik-letsencrypt.yaml:/etc/traefik/traefik.yaml"'})]}),"\n",(0,r.jsxs)(t.li,{children:["Comment out this openc3-traefik line: ",(0,r.jsx)(t.code,{children:'- "127.0.0.1:2900:2900"'})]}),"\n",(0,r.jsxs)(t.li,{children:["Comment out this openc3-traefik line: ",(0,r.jsx)(t.code,{children:'- "127.0.0.1:2943:2943"'})]}),"\n",(0,r.jsxs)(t.li,{children:["Uncomment out this openc3-traefik line: ",(0,r.jsx)(t.code,{children:'- "80:2900"'})]}),"\n",(0,r.jsxs)(t.li,{children:["Uncomment out this openc3-traefik line: ",(0,r.jsx)(t.code,{children:'- "443:2943"'})]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["Start COSMOS","\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"On Linux/Mac: ./openc3.sh run"}),"\n",(0,r.jsx)(t.li,{children:"On Windows: openc3.bat run"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["Enterprise Only: After approximately 2 minutes, open a web browser to ",(0,r.jsx)(t.a,{href:"https://mydomain.com/auth/",children:"https://mydomain.com/auth/"}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:'If you run "docker ps", you can watch until the openc3-cosmos-enterprise-init container completes, at which point the system should be fully configured and ready to use.'}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["Enterprise Only: ",(0,r.jsx)(t.strong,{children:"IMPORTANT"}),": You must configure Keycloak before accessing ",(0,r.jsx)(t.a,{href:"https://mydomain.com",children:"https://mydomain.com"})," to get to the main COSMOS app and Grafana to work (you'll just see a blank blue page until you do this) - Please follow the Keycloak documentation in our ",(0,r.jsx)(t.a,{href:"https://github.com/OpenC3/cosmos-enterprise/blob/main/docs/OpenC3%20COSMOS%20Enterprise%20Edition%20User's%20Manual.pdf",children:"User's Manual"})]}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"configure-cosmos-enterprise-for-tls-when-running-in-kubernetes",children:"Configure COSMOS Enterprise for TLS when running in Kubernetes"}),"\n",(0,r.jsx)(t.p,{children:"Follow earlier instructions to obtain your private key, public key, and to modify cacert.pem as necessary."}),"\n",(0,r.jsx)(t.p,{children:"In most Kubernetes environments, COSMOS will use a separate platform provided load balancer as the TLS termination point. Follow the directions for your specific Kubernetes environment to configure this load balancer with the TLS keys. Don't forget to update the cacert.pem file for COSMOS (and create the secret defined below) so that COSMOS can recognize the CA that issued your keys. As of COSMOS Enterprise 6.4, the create_secrets.sh script will create a secret called openc3-cacert to hold this file. This file is automatically mounted into each container that needs it at /devel/cacert.pem. Our helm charts also set the appropriate environment variables to use this file."}),"\n",(0,r.jsx)(t.p,{children:"You will also need to correctly set several values in the helm chart values.yaml file to configure for TLS. The relevant values are described in the following table."}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Value Name"}),(0,r.jsx)(t.th,{children:"Description"}),(0,r.jsx)(t.th,{children:"Default Value"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"global.cosmosdomain"}),(0,r.jsx)(t.td,{children:"The domain name that cosmos will be hosted at"}),(0,r.jsx)(t.td,{children:"cosmos.openc3.com"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"ssl"}),(0,r.jsx)(t.td,{children:"This flag should be set to true if you are using SSL/TLS even with an external load balancer"}),(0,r.jsx)(t.td,{children:"true"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"traefik.tlsCerts"}),(0,r.jsx)(t.td,{children:"Set this flag to true if you are going to use Traefik as your SSL endpoint with given certs"}),(0,r.jsx)(t.td,{children:"false"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"traefik.letsEncrypt"}),(0,r.jsx)(t.td,{children:"Set this flag to true if you want Traefik to acquire certs from Lets Encrypt. Will only work on the public internet."}),(0,r.jsx)(t.td,{children:"false"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"traefik.letsEncryptEmail"}),(0,r.jsx)(t.td,{children:"Email address given to Lets Encrypt when issuing certs"}),(0,r.jsx)(t.td,{children:"false"})]})]})]}),"\n",(0,r.jsx)(t.p,{children:"Additionally the following secrets will need to be defined based on how you set the above values."}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Secret Name"}),(0,r.jsx)(t.th,{children:"Description"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"openc3-cacert"}),(0,r.jsx)(t.td,{children:"This should always be set with the cacert.pem file used by COSMOS (even if just using public certificates). Be sure to append the full certificate chain from your private CA so that COSMOS can verify certificates successfully. Without doing this you will be guaranteed to receive SSL errors."})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"openc3-traefik-cert"}),(0,r.jsx)(t.td,{children:"Public key provided to Traefik if traefik.tlsCerts is true"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"openc3-traefik-key"}),(0,r.jsx)(t.td,{children:"Private key provided to Traefik if traefik.tlsCerts is true"})]})]})]})]})}function d(e={}){let{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},2840:function(e,t,i){i.d(t,{Z:function(){return a},a:function(){return o}});var n=i(2784);let r={},s=n.createContext(r);function o(e){let t=n.useContext(s);return n.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([["3649"],{4016:function(e,n,t){t.r(n),t.d(n,{default:()=>h,frontMatter:()=>c,metadata:()=>i,assets:()=>a,toc:()=>l,contentTitle:()=>r});var i=JSON.parse('{"id":"guides/cfs","title":"COSMOS and NASA cFS","description":"Tutorial for integrating with NASA cFS","source":"@site/docs/guides/cfs.md","sourceDirName":"guides","slug":"/guides/cfs","permalink":"/tools/staticdocs/docs/guides/cfs","draft":false,"unlisted":false,"editUrl":"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/guides/cfs.md","tags":[],"version":"current","frontMatter":{"title":"COSMOS and NASA cFS","description":"Tutorial for integrating with NASA cFS","sidebar_custom_props":{"myEmoji":"\uD83D\uDE80"}},"sidebar":"defaultSidebar","previous":{"title":"Bridges","permalink":"/tools/staticdocs/docs/guides/bridges"},"next":{"title":"Custom Widgets","permalink":"/tools/staticdocs/docs/guides/custom-widgets"}}'),s=t("2322"),o=t("2840");let c={title:"COSMOS and NASA cFS",description:"Tutorial for integrating with NASA cFS",sidebar_custom_props:{myEmoji:"\uD83D\uDE80"}},r=void 0,a={},l=[{value:"Working configuration",id:"working-configuration",level:2},{value:"Setting up COSMOS",id:"setting-up-cosmos",level:2},{value:"Configuring COSMOS",id:"configuring-cosmos",level:3},{value:"Setting up cFS",id:"setting-up-cfs",level:2},{value:"Clone cFS",id:"clone-cfs",level:3},{value:"Create Dockerfile in cFS dir",id:"create-dockerfile-in-cfs-dir",level:3},{value:"Build and run cFS",id:"build-and-run-cfs",level:3},{value:"Creating a COSMOS plugin for TM/TC interface with cFS",id:"creating-a-cosmos-plugin-for-tmtc-interface-with-cfs",level:2},{value:"Creating TM/TC definitions",id:"creating-tmtc-definitions",level:2},{value:"Uploading the plugin",id:"uploading-the-plugin",level:2}];function d(e){let n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"working-configuration",children:"Working configuration"}),"\n",(0,s.jsx)(n.p,{children:"This tutorial has been tested using the following components:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["COSMOS v6 release ",(0,s.jsx)(n.a,{href:"https://github.com/OpenC3/cosmos/releases/tag/v6.3.0",children:"6.3.0"})]}),"\n",(0,s.jsx)(n.li,{children:"cFS main-branch commit: 0ba1faa (April 23, 2025)"}),"\n",(0,s.jsx)(n.li,{children:"Docker Desktop 4.40.0 on MacOS"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Replace all ",(0,s.jsx)(n.code,{children:"<xxxxxx>"})," with your matching paths and names. Example: ",(0,s.jsx)(n.code,{children:"<USERNAME>"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"setting-up-cosmos",children:"Setting up COSMOS"}),"\n",(0,s.jsxs)(n.p,{children:["Install COSMOS according to the official ",(0,s.jsx)(n.a,{href:"/tools/staticdocs/docs/getting-started/installation",children:"installation"})," instructions."]}),"\n",(0,s.jsx)(n.h3,{id:"configuring-cosmos",children:"Configuring COSMOS"}),"\n",(0,s.jsxs)(n.p,{children:["Change the Docker configuration for the interoperability with NASA cFS. For\nsubscribing to the telemetry, you have to append a port binding in the file\n",(0,s.jsx)(n.code,{children:"compose.yaml"})," under the section ",(0,s.jsx)(n.code,{children:"openc3-operator"}),". The port number has to\nmatch with the port number cFS is sending the telemetry on."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'openc3-operator:\n ports:\n - "1235:1235/udp"\n'})}),"\n",(0,s.jsx)(n.p,{children:"Run COSMOS, the first run takes a while (~15 min)."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3.sh start\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When started, connect with a browser to ",(0,s.jsx)(n.a,{href:"http://localhost:2900",children:"http://localhost:2900"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"For shutting down COSMOS:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openc3.sh stop\n"})}),"\n",(0,s.jsx)(n.h2,{id:"setting-up-cfs",children:"Setting up cFS"}),"\n",(0,s.jsxs)(n.p,{children:["To run ",(0,s.jsx)(n.a,{href:"https://github.com/nasa/cFS",children:"NASA cFS"})," as a Docker container do the following:"]}),"\n",(0,s.jsx)(n.h3,{id:"clone-cfs",children:"Clone cFS"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"git clone --recurse-submodules https://github.com/nasa/cFS.git\n"})}),"\n",(0,s.jsx)(n.h3,{id:"create-dockerfile-in-cfs-dir",children:"Create Dockerfile in cFS dir"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-docker",children:'FROM ubuntu:25.04 AS builder\n\nARG DEBIAN_FRONTEND=noninteractive\nARG SIMULATION=native\nENV SIMULATION=${SIMULATION}\nARG BUILDTYPE=debug\nENV BUILDTYPE=${BUILDTYPE}\nARG OMIT_DEPRECATED=true\nENV OMIT_DEPRECATED=${OMIT_DEPRECATED}\n\nRUN \\\n apt-get update && \\\n apt-get -y upgrade && \\\n apt-get install -y build-essential git cmake && \\\n rm -rf /var/lib/apt/lists/*\n\nWORKDIR /cFS\nCOPY . .\n\nRUN git submodule init \\\n && git submodule update \\\n && cp cfe/cmake/Makefile.sample Makefile \\\n && cp -r cfe/cmake/sample_defs .\n\nRUN make prep\nRUN make\nRUN make install\n\nFROM ubuntu:25.04\nCOPY --from=builder /cFS/build /cFS/build\nWORKDIR /cFS/build/exe/cpu1\nENTRYPOINT [ "./core-cpu1" ]\n'})}),"\n",(0,s.jsx)(n.h3,{id:"build-and-run-cfs",children:"Build and run cFS"}),"\n",(0,s.jsxs)(n.p,{children:["Note we're connecting to the COSMOS network (",(0,s.jsx)(n.code,{children:"docker network ls"}),") and exposing the cFS ports."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker build -t cfs .\ndocker run --cap-add CAP_SYS_RESOURCE --net=cosmos-project_default --name cfs -p1234:1234/udp -p1235:1235 cfs\n"})}),"\n",(0,s.jsx)(n.h2,{id:"creating-a-cosmos-plugin-for-tmtc-interface-with-cfs",children:"Creating a COSMOS plugin for TM/TC interface with cFS"}),"\n",(0,s.jsxs)(n.p,{children:["The detailed instructions how to create a plugin, can be found\n",(0,s.jsx)(n.a,{href:"/tools/staticdocs/docs/getting-started/gettingstarted",children:"here"}),', in the chapter "Interfacing with Your Hardware".']}),"\n",(0,s.jsxs)(n.p,{children:["Create a new plugin with the name ",(0,s.jsx)(n.code,{children:"CFS"}),". ",(0,s.jsx)(n.code,{children:"CFS"})," is the name of the plugin and\nmust be in capital letters according to the COSMOS documentation. This command\nshould create the plugin structure. Then cd into the plugin to create the target."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"# cd .. to the location of the cfs dir\n$PATH_TO_OPENC3/openc3.sh cli generate plugin CFS\ncd openc3-cosmos-cfs\n$PATH_TO_OPENC3/openc3.sh cli generate target CFS\n"})}),"\n",(0,s.jsxs)(n.p,{children:["In this newly created plugin, change the ",(0,s.jsx)(n.code,{children:"plugin.txt"})," file, so that the\ncommunication happens over UDP. ",(0,s.jsx)(n.code,{children:"port_tm"})," is the port number on which cFS\nsends the telemetry messages. ",(0,s.jsx)(n.code,{children:"port_tc"})," indicates the port on which cFS listens to the\ntelecommands."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:"VARIABLE ip 127.0.0.1\nVARIABLE port_tm 1235\nVARIABLE port_tc 1234\nVARIABLE cfs_target_name CFS\n\nTARGET CFS <%= cfs_target_name %>\n# hostname write_dest_port read_port write_src_port interface_address ttl write_timeout read_timeout bind_address\nINTERFACE <%= cfs_target_name %>_INT udp_interface.rb <%= ip %> <%= port_tc %> <%= port_tm %> nil nil 128 nil nil\n MAP_TARGET <%= cfs_target_name %>\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Note that the two arguments to the ",(0,s.jsx)(n.code,{children:"TARGET"})," parameter are:"]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["the physical target name that should match the name of the plugin, i.e. ",(0,s.jsx)(n.code,{children:"CFS"}),".\nThis name must match the folder name in the ",(0,s.jsx)(n.code,{children:"targets"})," folder. Example: for the\n",(0,s.jsx)(n.code,{children:"CFS"})," plugin, the target specifications must be under\n",(0,s.jsx)(n.code,{children:"openc3-cosmos-cfs/targets/CFS"}),". If you don't follow this\nconvention, the server will refuse to install your plugin at the following steps."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"the name of your target and how it is shown in the user interface."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["In this example, we keep both names to be ",(0,s.jsx)(n.code,{children:"CFS"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"creating-tmtc-definitions",children:"Creating TM/TC definitions"}),"\n",(0,s.jsx)(n.p,{children:"Change to the target folder and remove the existing files and create own files."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cd openc3-cosmos-cfs/targets/CFS/cmd_tlm\nrm *\ntouch cfs_cmds.txt\ntouch cfs_tlm.txt\ntouch to_lab_cmds.txt\n"})}),"\n",(0,s.jsx)(n.p,{children:"Open these newly created files in a text editor and fill them with following\ncontent."}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"to_lab_cmds.txt"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:'COMMAND CFS TO_LAB_ENABLE BIG_ENDIAN "Enable telemetry"\n # NAME BITS TYPE min VAL max VAL init VAL DESCRIPTION\n APPEND_ID_PARAMETER STREAM_ID 16 UINT 0x1880 0x1880 0x1880 "Stream ID"\n FORMAT_STRING "0x%04X"\n APPEND_PARAMETER SEQUENCE 16 UINT 0xC000 MAX_UINT16 0xC000 ""\n FORMAT_STRING "0x%04X"\n APPEND_PARAMETER PKT_LEN 16 UINT 0x0001 0xFFFF 0x0012 "length of the packet"\n APPEND_PARAMETER CMD_ID 8 UINT 6 6 6 ""\n APPEND_PARAMETER CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0x98 ""\n FORMAT_STRING "0x%2X"\n APPEND_PARAMETER DEST_IP 144 STRING "127.0.0.1" "Destination IP, i.e. 172.16.9.112, pc-57"\n'})}),"\n",(0,s.jsx)(n.admonition,{title:"Enabling Telemetry",type:"info",children:(0,s.jsxs)(n.p,{children:["The command ",(0,s.jsx)(n.code,{children:"0x1880"})," is needed to enable telemetry. When the cFS receives\nthis command, it starts sending telemetry to the IP address provided via the\n",(0,s.jsx)(n.code,{children:"DEST_IP"})," field."]})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"cfs_cmds.txt"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:'COMMAND CFS NOOP BIG_ENDIAN "NOOP Command"\n # cFS primary header\n APPEND_ID_PARAMETER STREAM_ID 16 UINT 0x1882 0x1882 0x1882 "Packet Identification"\n FORMAT_STRING "0x%04X"\n APPEND_PARAMETER SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 ""\n FORMAT_STRING "0x%04X"\n APPEND_PARAMETER PKT_LEN 16 UINT 0x0001 0x0001 0x0001 "Packet length"\n # cFS CMD secondary header\n APPEND_PARAMETER CMD_ID 8 UINT 0 0 0 ""\n APPEND_PARAMETER CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 MIN_UINT8 ""\n\nCOMMAND CFS RESET BIG_ENDIAN "Reset Counters Command"\n APPEND_ID_PARAMETER STREAM_ID 16 UINT 0x1882 0x1882 0x1882 "Packet Identification"\n FORMAT_STRING "0x%04X"\n APPEND_PARAMETER SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 ""\n FORMAT_STRING "0x%04X"\n APPEND_PARAMETER PKT_LEN 16 UINT 0x0001 0x0001 0x0001 "Packet length"\n APPEND_PARAMETER CMD_ID 8 UINT 1 1 1 ""\n APPEND_PARAMETER CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 MIN_UINT8 ""\n\nCOMMAND CFS PROCESS BIG_ENDIAN "Process Command"\n APPEND_ID_PARAMETER STREAM_ID 16 UINT 0x1882 0x1882 0x1882 "Packet Identification"\n FORMAT_STRING "0x%04X"\n APPEND_PARAMETER SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 ""\n FORMAT_STRING "0x%04X"\n APPEND_PARAMETER PKT_LEN 16 UINT 0x0001 0x0001 0x0001 "Packet length"\n APPEND_PARAMETER CMD_ID 8 UINT 2 2 2 ""\n APPEND_PARAMETER CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 MIN_UINT8 ""\n'})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"cfs_tlm.txt"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-ruby",children:'TELEMETRY CFS HK BIG_ENDIAN "housekeeping telemetry"\n # NAME BITS TYPE ID DESCRIPTION\n APPEND_ID_ITEM STREAM_ID 16 UINT 0x0883 "Stream ID"\n FORMAT_STRING "0x%04X"\n APPEND_ITEM SEQUENCE 16 UINT "Packet Sequence"\n FORMAT_STRING "0x%04X"\n APPEND_ITEM PKT_LEN 16 UINT "Length of the packet"\n # telemetry secondary header\n APPEND_ITEM SECONDS 32 UINT ""\n UNITS Seconds sec\n APPEND_ITEM SUBSECS 16 UINT ""\n UNITS Milliseconds ms\n # some bytes not known for what\n APPEND_ITEM SPARE2ALIGN 32 UINT "Spares"\n # payload\n APPEND_ITEM CMD_ERRS 8 UINT "Command Error Counter"\n APPEND_ITEM CMD_CNT 8 UINT "Command Counter"\n # spare / alignment\n APPEND_ITEM SPARE 16 UINT "Spares"\n'})}),"\n",(0,s.jsx)(n.p,{children:"Build the plugin from the base of your plugin folder:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"# cd openc3-cosmos-cfs\n$PATH_TO_OPENC3/openc3.sh cli rake build VERSION=1.0.0\n"})}),"\n",(0,s.jsx)(n.admonition,{title:"Plugin versioning",type:"info",children:(0,s.jsx)(n.p,{children:"Do not forget to change the version number with every build if you want to\nbetter distinguish between the versions of the plugin. When the version is\nseen in the plugin's .gem file name, it is easier to visualize the existing\nversions and the newly uploaded versions."})}),"\n",(0,s.jsx)(n.admonition,{title:"Plugin parameters",type:"info",children:(0,s.jsxs)(n.p,{children:["Multiple parameters are available for the plugin configuration. See the ",(0,s.jsx)(n.a,{href:"/tools/staticdocs/docs/configuration/plugins",children:"plugin"})," page."]})}),"\n",(0,s.jsx)(n.h2,{id:"uploading-the-plugin",children:"Uploading the plugin"}),"\n",(0,s.jsx)(n.p,{children:"After the plugin has been built, you can import the plugin in the admin area of\nthe page."}),"\n",(0,s.jsxs)(n.p,{children:["Connect with a browser to\n",(0,s.jsx)(n.a,{href:"http://localhost:2900/tools/admin",children:"http://localhost:2900/tools/admin"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:['Click on the "Install New Plugin" button and navigate to where your plugin is stored and select\nthe ',(0,s.jsx)(n.code,{children:"openc3-cosmos-cfs-1.0.0.gem"})," file. Right of the selection line click on ",(0,s.jsx)(n.code,{children:"Install"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"Determine the IP address the cFS container and COSMOS operator container are running at:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'docker network ls\nNETWORK ID NAME DRIVER SCOPE\nd842f813f1c7 cosmos-project_default bridge local\n\ndocker network inspect cosmos-project_default \n[\n {\n "Name": "cosmos-project_default ",\n ...\n "Containers": {\n "03cb6bf1b27c631fad1366e9342aeaa5b80f458a437195e4a95e674bb5f5983d": {\n "Name": "cfs",\n "IPv4Address": "172.20.0.9/16",\n },\n "ceb9ea99b00849fd8867dcd1646838fef3471f7d64b69014703dbedbcc8147fc": {\n "Name": "openc3_openc3-operator_1",\n "IPv4Address": "172.20.0.8/16",\n }\n }\n ...\n }\n]\n'})}),"\n",(0,s.jsxs)(n.p,{children:["When using this plugin, make sure to change the ",(0,s.jsx)(n.code,{children:"ip"})," variable during uploading\nto match where cFS is running. In the example above you would set it to 172.20.0.9.\n",(0,s.jsx)(n.code,{children:"port_tm"})," is the port number on which cFS is sending the telemetry messages.\n",(0,s.jsx)(n.code,{children:"port_tc"})," indicates the port on cFS is listening for telecommands."]}),"\n",(0,s.jsxs)(n.p,{children:["Under ",(0,s.jsx)(n.code,{children:"cfs_target_name"})," you can change the target name of this plugin. This\nstep is optional as long as you are fine with your plugin showing up as ",(0,s.jsx)(n.code,{children:"CFS"}),"."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Plugin Variable Settings",src:t(3191).Z+"",width:"1183",height:"270"})}),"\n",(0,s.jsx)(n.admonition,{title:"Port subscription",type:"warning",children:(0,s.jsx)(n.p,{children:"The last uploaded plugin on COSMOS will subscribe to TM on port 1235.\nOther plugins will not receive any TM anymore."})}),"\n",(0,s.jsx)(n.admonition,{title:"Typo errors",type:"info",children:(0,s.jsx)(n.p,{children:"Presence of typos in one of the plugin files can cause problems when uploading and installing\nthe plugin's .gem file. Make sure your configuration is typo-free."})}),"\n",(0,s.jsxs)(n.p,{children:["In the example above, the operator image is running at 172.20.0.8. To enable telemetry, go to the browser and connect to\n",(0,s.jsx)(n.a,{href:"http://localhost:2900/tools/cmdsender/CFS/TO_LAB_ENABLE",children:"http://localhost:2900/tools/cmdsender/CFS/TO_LAB_ENABLE"}),". Change the ",(0,s.jsx)(n.code,{children:"DEST_IP"})," to the IP address of the operator image (172.20.0.8) and send the command."]}),"\n",(0,s.jsxs)(n.p,{children:["Under ",(0,s.jsx)(n.a,{href:"http://localhost:2900/tools/cmdtlmserver/tlm-packets",children:"http://localhost:2900/tools/cmdtlmserver/tlm-packets"}),", you should see the incoming packets. Note in the CmdTlmServer you will also see CFS_INT UNKNOWN packets because we did not define the full cFS packet set. That exercise is left to the reader."]})]})}function h(e={}){let{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},3191:function(e,n,t){t.d(n,{Z:function(){return i}});let i=t.p+"assets/images/plugin_variables-6904e1d9003a6c8c530bd1f738f7966217beca7d3064b40670e7a4ab7e200927.png"},2840:function(e,n,t){t.d(n,{Z:function(){return r},a:function(){return c}});var i=t(2784);let s={},o=i.createContext(s);function c(e){let n=i.useContext(o);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([["4456"],{9779:function(e,t,o){o.r(t),o.d(t,{default:()=>u,frontMatter:()=>l,metadata:()=>s,assets:()=>c,toc:()=>a,contentTitle:()=>r});var s=JSON.parse('{"id":"tools/bucket-explorer","title":"Bucket Explorer","description":"File browser to the COSMOS backend bucket storage system","source":"@site/docs/tools/bucket-explorer.md","sourceDirName":"tools","slug":"/tools/bucket-explorer","permalink":"/tools/staticdocs/docs/tools/bucket-explorer","draft":false,"unlisted":false,"editUrl":"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/tools/bucket-explorer.md","tags":[],"version":"current","frontMatter":{"title":"Bucket Explorer","description":"File browser to the COSMOS backend bucket storage system","sidebar_custom_props":{"myEmoji":"\uD83D\uDEE0\uFE0F"}},"sidebar":"defaultSidebar","previous":{"title":"Autonomic (Enterprise)","permalink":"/tools/staticdocs/docs/tools/autonomic"},"next":{"title":"Calendar (Enterprise)","permalink":"/tools/staticdocs/docs/tools/calendar"}}'),n=o("2322"),i=o("2840");let l={title:"Bucket Explorer",description:"File browser to the COSMOS backend bucket storage system",sidebar_custom_props:{myEmoji:"\uD83D\uDEE0\uFE0F"}},r=void 0,c={},a=[{value:"Introduction",id:"introduction",level:2},{value:"Browsing Files",id:"browsing-files",level:2},{value:"Upload",id:"upload",level:3},{value:"Download",id:"download",level:3},{value:"Delete",id:"delete",level:3}];function d(e){let t={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",img:"img",p:"p",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,n.jsx)(t.p,{children:"Bucket Explorer is a file browser to the COSMOS backend bucket storage system. It allows you to view files in an intuitive file browser hierarchy and download them. Bucket Explorer works both with local installations of COSMOS as well as cloud deployments which utilize cloud storage such as AWS S3 and GCP Cloud Storage."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"Bucket Explorer",src:o(909).Z+"",width:"1271",height:"543"})}),"\n",(0,n.jsx)(t.h2,{id:"browsing-files",children:"Browsing Files"}),"\n",(0,n.jsxs)(t.p,{children:["At the top are the three standard COSMOS buckets: ",(0,n.jsx)(t.code,{children:"config"}),", ",(0,n.jsx)(t.code,{children:"logs"}),", and ",(0,n.jsx)(t.code,{children:"tools"}),". Each bucket contains top level folders named after the scope. In COSMOS Core the only scope is ",(0,n.jsx)(t.code,{children:"DEFAULT"}),". The ",(0,n.jsx)(t.code,{children:"config"})," bucket holds the COSMOS configuration which is populated as plugins are installed. The ",(0,n.jsx)(t.code,{children:"logs"})," bucket holds the COSMOS logs which are generated by the various COSMOS microservices (See ",(0,n.jsx)(t.a,{href:"/tools/staticdocs/docs/guides/logging",children:"Logging"})," for more info). These logs are gzipped to save storage space. The ",(0,n.jsx)(t.code,{children:"tools"})," bucket holds the source code for the built-in COSMOS tools as well as user created tools installed as plugins. Note that the search box only searches the current screen worth of files, e.g. it does not search the entire bucket."]}),"\n",(0,n.jsx)(t.admonition,{title:"Tools as Static Website",type:"note",children:(0,n.jsx)(t.p,{children:"Using bucket storage allows COSMOS to directly serve the tools as a static website and thus it must be a public bucket in cloud technology like S3"})}),"\n",(0,n.jsx)(t.h3,{id:"upload",children:"Upload"}),"\n",(0,n.jsxs)(t.p,{children:["Click the Upload icon to bring up a file browser to select a file to upload into the current bucket and path. Note that in ",(0,n.jsx)(t.a,{href:"https://openc3.com/enterprise",children:"COSMOS Enterprise"})," you can only upload files to the config/DEFAULT/targets_modified folder unless you're an Admin."]}),"\n",(0,n.jsx)(t.h3,{id:"download",children:"Download"}),"\n",(0,n.jsx)(t.p,{children:"Click the Download icon to download any of the individual files from any bucket and path."}),"\n",(0,n.jsx)(t.h3,{id:"delete",children:"Delete"}),"\n",(0,n.jsxs)(t.p,{children:["Click the Trash icon to delete an individual file. Note that in ",(0,n.jsx)(t.a,{href:"https://openc3.com/enterprise",children:"COSMOS Enterprise"})," you can only delete files in the config/DEFAULT/targets_modified folder unless you're an Admin."]})]})}function u(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},909:function(e,t,o){o.d(t,{Z:function(){return s}});let s=o.p+"assets/images/bucket_explorer-ba88a20121198c3441a6af5302ab1a6ad62a171661037e9e3bfd312ca8bdb5ef.png"},2840:function(e,t,o){o.d(t,{Z:function(){return r},a:function(){return l}});var s=o(2784);let n={},i=s.createContext(n);function l(e){let t=s.useContext(i);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:l(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]);