Compare commits
No commits in common. 'gh-pages' and 'master' have entirely different histories.
80 changed files with 1782 additions and 9929 deletions
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
#mkdocs |
||||
site/ |
||||
docker-compose.yml |
||||
|
||||
# ignore scripts generated from templates |
||||
scripts/pages_init_setup.py |
||||
scripts/subdomains_init_setup.py |
||||
scripts/captain-hook-canary.service |
||||
scripts/captain_hook_canary.sh |
||||
scripts/captain_hook_pull_host.py |
||||
scripts/pod-webhooks.service |
||||
scripts/output/ |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
[submodule "b-captain-hook"] |
||||
path = b-captain-hook |
||||
url = https://git.charlesreid1.com/bots/b-captain-hook.git |
||||
[submodule "d-nginx-subdomains"] |
||||
path = d-nginx-subdomains |
||||
url = https://git.charlesreid1.com/docker/d-nginx-subdomains.git |
||||
[submodule "mkdocs-material"] |
||||
path = mkdocs-material |
||||
url = https://git.charlesreid1.com/charlesreid1/mkdocs-material |
@ -1,492 +0,0 @@
@@ -1,492 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html> |
||||
<html lang="en" class="no-js"> |
||||
<head> |
||||
|
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width,initial-scale=1"> |
||||
<meta http-equiv="x-ua-compatible" content="ie=edge"> |
||||
|
||||
|
||||
<link rel="canonical" href="https://pages.charlesreid1.com/pod-webhooks/adding/"> |
||||
|
||||
|
||||
|
||||
<meta name="lang:clipboard.copy" content="Copy to clipboard"> |
||||
|
||||
<meta name="lang:clipboard.copied" content="Copied to clipboard"> |
||||
|
||||
<meta name="lang:search.language" content="en"> |
||||
|
||||
<meta name="lang:search.pipeline.stopwords" content="True"> |
||||
|
||||
<meta name="lang:search.pipeline.trimmer" content="True"> |
||||
|
||||
<meta name="lang:search.result.none" content="No matching documents"> |
||||
|
||||
<meta name="lang:search.result.one" content="1 matching document"> |
||||
|
||||
<meta name="lang:search.result.other" content="# matching documents"> |
||||
|
||||
<meta name="lang:search.tokenizer" content="[\s\-]+"> |
||||
|
||||
<link rel="shortcut icon" href=".."> |
||||
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-3.0.3"> |
||||
|
||||
|
||||
|
||||
<title>Adding Webhooks - pod-webhooks</title> |
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/application.451f80e5.css"> |
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/application-palette.22915126.css"> |
||||
|
||||
|
||||
|
||||
|
||||
<meta name="theme-color" content="#2196f3"> |
||||
|
||||
|
||||
|
||||
<script src="../assets/javascripts/modernizr.1aa3b519.js"></script> |
||||
|
||||
|
||||
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin> |
||||
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono"> |
||||
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style> |
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/fonts/material-icons.css"> |
||||
|
||||
<link rel="stylesheet" href="../css/custom.css"> |
||||
|
||||
|
||||
</head> |
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-primary="blue" data-md-color-accent="blue"> |
||||
|
||||
<svg class="md-svg"> |
||||
<defs> |
||||
|
||||
|
||||
</defs> |
||||
</svg> |
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off"> |
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> |
||||
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label> |
||||
|
||||
<a href="../#adding-new-hooks" tabindex="1" class="md-skip"> |
||||
Skip to content |
||||
</a> |
||||
|
||||
|
||||
<header class="md-header" data-md-component="header"> |
||||
<nav class="md-header-nav md-grid"> |
||||
<div class="md-flex"> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<a href="https://pages.charlesreid1.com/pod-webhooks" title="pod-webhooks" class="md-header-nav__button md-logo"> |
||||
|
||||
<i class="md-icon">dns</i> |
||||
|
||||
</a> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--stretch"> |
||||
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title"> |
||||
|
||||
|
||||
<span class="md-header-nav__topic"> |
||||
pod-webhooks |
||||
</span> |
||||
<span class="md-header-nav__topic"> |
||||
Adding Webhooks |
||||
</span> |
||||
|
||||
|
||||
</div> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
|
||||
|
||||
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label> |
||||
|
||||
<div class="md-search" data-md-component="search" role="dialog"> |
||||
<label class="md-search__overlay" for="__search"></label> |
||||
<div class="md-search__inner" role="search"> |
||||
<form class="md-search__form" name="search"> |
||||
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active"> |
||||
<label class="md-icon md-search__icon" for="__search"></label> |
||||
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1"> |
||||
 |
||||
</button> |
||||
</form> |
||||
<div class="md-search__output"> |
||||
<div class="md-search__scrollwrap" data-md-scrollfix> |
||||
<div class="md-search-result" data-md-component="result"> |
||||
<div class="md-search-result__meta"> |
||||
Type to start searching |
||||
</div> |
||||
<ol class="md-search-result__list"></ol> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
</div> |
||||
|
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<div class="md-header-nav__source"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://git.charlesreid1.com/docker/pod-webhooks" title="Go to repository" class="md-source" data-md-source=""> |
||||
|
||||
<div class="md-source__repository"> |
||||
pod-webhooks |
||||
</div> |
||||
</a> |
||||
|
||||
</div> |
||||
</div> |
||||
|
||||
</div> |
||||
</nav> |
||||
</header> |
||||
|
||||
<div class="md-container"> |
||||
|
||||
|
||||
|
||||
<main class="md-main"> |
||||
<div class="md-main__inner md-grid" data-md-component="container"> |
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation"> |
||||
<div class="md-sidebar__scrollwrap"> |
||||
<div class="md-sidebar__inner"> |
||||
<nav class="md-nav md-nav--primary" data-md-level="0"> |
||||
<label class="md-nav__title md-nav__title--site" for="__drawer"> |
||||
<a href="https://pages.charlesreid1.com/pod-webhooks" title="pod-webhooks" class="md-nav__button md-logo"> |
||||
|
||||
<i class="md-icon">dns</i> |
||||
|
||||
</a> |
||||
pod-webhooks |
||||
</label> |
||||
|
||||
<div class="md-nav__source"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://git.charlesreid1.com/docker/pod-webhooks" title="Go to repository" class="md-source" data-md-source=""> |
||||
|
||||
<div class="md-source__repository"> |
||||
pod-webhooks |
||||
</div> |
||||
</a> |
||||
|
||||
</div> |
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href=".." title="Home" class="md-nav__link"> |
||||
Home |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--active"> |
||||
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc"> |
||||
|
||||
|
||||
<label class="md-nav__link md-nav__link--active" for="__toc"> |
||||
Adding Webhooks |
||||
</label> |
||||
|
||||
<a href="./" title="Adding Webhooks" class="md-nav__link md-nav__link--active"> |
||||
Adding Webhooks |
||||
</a> |
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary"> |
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#adding-new-hooks" title="Adding New Hooks" class="md-nav__link"> |
||||
Adding New Hooks |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#debugging-failed-hooks" title="Debugging Failed Hooks" class="md-nav__link"> |
||||
Debugging Failed Hooks |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul> |
||||
|
||||
</nav> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../running/" title="Running Captain Hook" class="md-nav__link"> |
||||
Running Captain Hook |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../services/" title="Captain Hook Startup Services" class="md-nav__link"> |
||||
Captain Hook Startup Services |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../canary/" title="Captain Hook's Canary" class="md-nav__link"> |
||||
Captain Hook's Canary |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
</ul> |
||||
</nav> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc"> |
||||
<div class="md-sidebar__scrollwrap"> |
||||
<div class="md-sidebar__inner"> |
||||
|
||||
<nav class="md-nav md-nav--secondary"> |
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#adding-new-hooks" title="Adding New Hooks" class="md-nav__link"> |
||||
Adding New Hooks |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#debugging-failed-hooks" title="Debugging Failed Hooks" class="md-nav__link"> |
||||
Debugging Failed Hooks |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul> |
||||
|
||||
</nav> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<div class="md-content"> |
||||
<article class="md-content__inner md-typeset"> |
||||
|
||||
|
||||
|
||||
<h1>Adding Webhooks</h1> |
||||
|
||||
<h2 id="adding-new-hooks">Adding New Hooks<a class="headerlink" href="#adding-new-hooks" title="Permanent link">¶</a></h2> |
||||
<p>To add a hook to Captain Hook:</p> |
||||
<ol> |
||||
<li> |
||||
<p>Create an executable script in <a href="https://git.charlesreid1.com/bots/b-captain-hook">bots/b-captain-hook</a> |
||||
on git.charlesreid1.com with the name of the action, the name of the repo (not the owner), |
||||
and the name of the branch in the filename. For example, <code>push-my-dotfiles-master</code> would be |
||||
matched every time I <code>push</code> changes to the <code>master</code> branch of any repository named <code>my-dotfiles</code>.</p> |
||||
</li> |
||||
<li> |
||||
<p>Add, commit, and push your hook to the master branch of Captain Hook</p> |
||||
</li> |
||||
<li> |
||||
<p>Wait about 15 seconds for the canary script to run (it has to update |
||||
the Captain Hook git repo running on the remote server to the latest version |
||||
and restart the webhooks-subdomains docker pod.)</p> |
||||
</li> |
||||
<li> |
||||
<p>Open the <code>my-dotfiles</code> repository on git.charlesreid1.com, go to the |
||||
Settings > Webhooks page, and add a Gitea webhook.</p> |
||||
</li> |
||||
<li> |
||||
<p>Enter info:</p> |
||||
<p>a. Payload URL is the Captain Hook server, which is <code>https://hooks.charlesreid1.com/webhook</code>. |
||||
b. Content type is <code>application/json</code> |
||||
c. Secret is (that's my little secret) |
||||
d. Pick what events you would like to trigger webhooks, usually "just the push event"</p> |
||||
</li> |
||||
<li> |
||||
<p>Save the webhook, then click on the webhook again to open it back up. |
||||
Scroll down to the bottom right and click "Test Delivery". </p> |
||||
</li> |
||||
</ol> |
||||
<p>You should see a green success sign. </p> |
||||
<h2 id="debugging-failed-hooks">Debugging Failed Hooks<a class="headerlink" href="#debugging-failed-hooks" title="Permanent link">¶</a></h2> |
||||
<p>If you see a red warning sign:</p> |
||||
<ul> |
||||
<li>Ensure the webhooks docker pod is actually running okay (<code>docker ps</code> on the host machine)</li> |
||||
<li>Ensure port 5000 is open in the Captain Hook container, and on the host machine</li> |
||||
<li>Ensure you can see port 5000 of the <code>pod-webhooks</code> host machine from the <code>pod-charlesreid1</code> host machine</li> |
||||
<li>Ensure there is actually a hook in the <code>hooks/</code> directory of the Captain Hook repo</li> |
||||
</ul> |
||||
<p>Captain Hook repo: <a href="https://git.charlesreid1.com/bots/b-captain-hook">https://git.charlesreid1.com/bots/b-captain-hook</a></p> |
||||
<p>Captain Hook repo (Github mirror): <a href="https://github.com/charlesreid1-docker/b-captain-hook">https://github.com/charlesreid1-docker/b-captain-hook</a></p> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article> |
||||
</div> |
||||
</div> |
||||
</main> |
||||
|
||||
|
||||
<footer class="md-footer"> |
||||
|
||||
<div class="md-footer-nav"> |
||||
<nav class="md-footer-nav__inner md-grid"> |
||||
|
||||
<a href=".." title="Home" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev"> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"> |
||||
<span class="md-flex__ellipsis"> |
||||
<span class="md-footer-nav__direction"> |
||||
Previous |
||||
</span> |
||||
Home |
||||
</span> |
||||
</div> |
||||
</a> |
||||
|
||||
|
||||
<a href="../running/" title="Running Captain Hook" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next"> |
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"> |
||||
<span class="md-flex__ellipsis"> |
||||
<span class="md-footer-nav__direction"> |
||||
Next |
||||
</span> |
||||
Running Captain Hook |
||||
</span> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i> |
||||
</div> |
||||
</a> |
||||
|
||||
</nav> |
||||
</div> |
||||
|
||||
<div class="md-footer-meta md-typeset"> |
||||
<div class="md-footer-meta__inner md-grid"> |
||||
<div class="md-footer-copyright"> |
||||
|
||||
<div class="md-footer-copyright__highlight"> |
||||
Copyright © 2018 <a href="https://charlesreid1.com">Charles Reid</a>, released under the <a href="https://opensource.org/licenses/MIT">MIT license</a> |
||||
</div> |
||||
|
||||
powered by |
||||
<a href="https://www.mkdocs.org">MkDocs</a> |
||||
and |
||||
<a href="https://squidfunk.github.io/mkdocs-material/"> |
||||
Material for MkDocs</a> |
||||
</div> |
||||
|
||||
|
||||
|
||||
</div> |
||||
</div> |
||||
</footer> |
||||
|
||||
</div> |
||||
|
||||
<script src="../assets/javascripts/application.e72fd936.js"></script> |
||||
|
||||
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script> |
||||
|
||||
<script src="../search/main.js"></script> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</body> |
||||
</html> |
@ -1,580 +0,0 @@
@@ -1,580 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html> |
||||
<html lang="en" class="no-js"> |
||||
<head> |
||||
|
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width,initial-scale=1"> |
||||
<meta http-equiv="x-ua-compatible" content="ie=edge"> |
||||
|
||||
|
||||
<link rel="canonical" href="https://pages.charlesreid1.com/pod-webhooks/canary/"> |
||||
|
||||
|
||||
|
||||
<meta name="lang:clipboard.copy" content="Copy to clipboard"> |
||||
|
||||
<meta name="lang:clipboard.copied" content="Copied to clipboard"> |
||||
|
||||
<meta name="lang:search.language" content="en"> |
||||
|
||||
<meta name="lang:search.pipeline.stopwords" content="True"> |
||||
|
||||
<meta name="lang:search.pipeline.trimmer" content="True"> |
||||
|
||||
<meta name="lang:search.result.none" content="No matching documents"> |
||||
|
||||
<meta name="lang:search.result.one" content="1 matching document"> |
||||
|
||||
<meta name="lang:search.result.other" content="# matching documents"> |
||||
|
||||
<meta name="lang:search.tokenizer" content="[\s\-]+"> |
||||
|
||||
<link rel="shortcut icon" href=".."> |
||||
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-3.0.3"> |
||||
|
||||
|
||||
|
||||
<title>Captain Hook's Canary - pod-webhooks</title> |
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/application.451f80e5.css"> |
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/application-palette.22915126.css"> |
||||
|
||||
|
||||
|
||||
|
||||
<meta name="theme-color" content="#2196f3"> |
||||
|
||||
|
||||
|
||||
<script src="../assets/javascripts/modernizr.1aa3b519.js"></script> |
||||
|
||||
|
||||
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin> |
||||
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono"> |
||||
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style> |
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/fonts/material-icons.css"> |
||||
|
||||
<link rel="stylesheet" href="../css/custom.css"> |
||||
|
||||
|
||||
</head> |
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-primary="blue" data-md-color-accent="blue"> |
||||
|
||||
<svg class="md-svg"> |
||||
<defs> |
||||
|
||||
|
||||
</defs> |
||||
</svg> |
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off"> |
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> |
||||
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label> |
||||
|
||||
<a href="../#captain-hooks-canary" tabindex="1" class="md-skip"> |
||||
Skip to content |
||||
</a> |
||||
|
||||
|
||||
<header class="md-header" data-md-component="header"> |
||||
<nav class="md-header-nav md-grid"> |
||||
<div class="md-flex"> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<a href="https://pages.charlesreid1.com/pod-webhooks" title="pod-webhooks" class="md-header-nav__button md-logo"> |
||||
|
||||
<i class="md-icon">dns</i> |
||||
|
||||
</a> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--stretch"> |
||||
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title"> |
||||
|
||||
|
||||
<span class="md-header-nav__topic"> |
||||
pod-webhooks |
||||
</span> |
||||
<span class="md-header-nav__topic"> |
||||
Captain Hook's Canary |
||||
</span> |
||||
|
||||
|
||||
</div> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
|
||||
|
||||
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label> |
||||
|
||||
<div class="md-search" data-md-component="search" role="dialog"> |
||||
<label class="md-search__overlay" for="__search"></label> |
||||
<div class="md-search__inner" role="search"> |
||||
<form class="md-search__form" name="search"> |
||||
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active"> |
||||
<label class="md-icon md-search__icon" for="__search"></label> |
||||
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1"> |
||||
 |
||||
</button> |
||||
</form> |
||||
<div class="md-search__output"> |
||||
<div class="md-search__scrollwrap" data-md-scrollfix> |
||||
<div class="md-search-result" data-md-component="result"> |
||||
<div class="md-search-result__meta"> |
||||
Type to start searching |
||||
</div> |
||||
<ol class="md-search-result__list"></ol> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
</div> |
||||
|
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<div class="md-header-nav__source"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://git.charlesreid1.com/docker/pod-webhooks" title="Go to repository" class="md-source" data-md-source=""> |
||||
|
||||
<div class="md-source__repository"> |
||||
pod-webhooks |
||||
</div> |
||||
</a> |
||||
|
||||
</div> |
||||
</div> |
||||
|
||||
</div> |
||||
</nav> |
||||
</header> |
||||
|
||||
<div class="md-container"> |
||||
|
||||
|
||||
|
||||
<main class="md-main"> |
||||
<div class="md-main__inner md-grid" data-md-component="container"> |
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation"> |
||||
<div class="md-sidebar__scrollwrap"> |
||||
<div class="md-sidebar__inner"> |
||||
<nav class="md-nav md-nav--primary" data-md-level="0"> |
||||
<label class="md-nav__title md-nav__title--site" for="__drawer"> |
||||
<a href="https://pages.charlesreid1.com/pod-webhooks" title="pod-webhooks" class="md-nav__button md-logo"> |
||||
|
||||
<i class="md-icon">dns</i> |
||||
|
||||
</a> |
||||
pod-webhooks |
||||
</label> |
||||
|
||||
<div class="md-nav__source"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://git.charlesreid1.com/docker/pod-webhooks" title="Go to repository" class="md-source" data-md-source=""> |
||||
|
||||
<div class="md-source__repository"> |
||||
pod-webhooks |
||||
</div> |
||||
</a> |
||||
|
||||
</div> |
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href=".." title="Home" class="md-nav__link"> |
||||
Home |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../adding/" title="Adding Webhooks" class="md-nav__link"> |
||||
Adding Webhooks |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../running/" title="Running Captain Hook" class="md-nav__link"> |
||||
Running Captain Hook |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../services/" title="Captain Hook Startup Services" class="md-nav__link"> |
||||
Captain Hook Startup Services |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--active"> |
||||
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc"> |
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__link md-nav__link--active" for="__toc"> |
||||
Captain Hook's Canary |
||||
</label> |
||||
|
||||
<a href="./" title="Captain Hook's Canary" class="md-nav__link md-nav__link--active"> |
||||
Captain Hook's Canary |
||||
</a> |
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#the-canary-bash-script" title="The Canary Bash Script" class="md-nav__link"> |
||||
The Canary Bash Script |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#the-pull-host-captain-hook-script" title="The Pull Host Captain Hook Script" class="md-nav__link"> |
||||
The Pull Host Captain Hook Script |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#the-canary-startup-script" title="The Canary Startup Script" class="md-nav__link"> |
||||
The Canary Startup Script |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul> |
||||
|
||||
</nav> |
||||
|
||||
</li> |
||||
|
||||
|
||||
</ul> |
||||
</nav> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc"> |
||||
<div class="md-sidebar__scrollwrap"> |
||||
<div class="md-sidebar__inner"> |
||||
|
||||
<nav class="md-nav md-nav--secondary"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#the-canary-bash-script" title="The Canary Bash Script" class="md-nav__link"> |
||||
The Canary Bash Script |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#the-pull-host-captain-hook-script" title="The Pull Host Captain Hook Script" class="md-nav__link"> |
||||
The Pull Host Captain Hook Script |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#the-canary-startup-script" title="The Canary Startup Script" class="md-nav__link"> |
||||
The Canary Startup Script |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul> |
||||
|
||||
</nav> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<div class="md-content"> |
||||
<article class="md-content__inner md-typeset"> |
||||
|
||||
|
||||
|
||||
<h1 id="captain-hooks-canary">Captain Hook's Canary<a class="headerlink" href="#captain-hooks-canary" title="Permanent link">¶</a></h1> |
||||
<p>First things first: Captain Hook is the webhook server that |
||||
is part of the webhooks docker pod. It receives webhooks |
||||
from Github and Gitea and uses them to trigger scrips. |
||||
Links to <a href="https://pages.charlesreid1.com/b-captain-hook">documentation</a> |
||||
and <a href="https://git.charlesreid1.com/bots/b-captain-hook">code</a> |
||||
for Captain Hook.</p> |
||||
<p>Captain Hook's Canary is a mechanism by which the Captain Hook |
||||
webhooks server (running in a docker container) can trigger an action |
||||
on the host machine (running the pod). In this case the action is to |
||||
update Captain Hook and restart the docker pod anytime a webhook is |
||||
received indicating the Captain Hook repo has changed.</p> |
||||
<p>This is done by bind-mounting a host directory at <code>/tmp/triggers/</code> |
||||
inside the Captain Hook docker container. When Captain Hook receives |
||||
a webhook from Github or Gitea that indicates the Captain Hook |
||||
repo (<a href="https://git.charlesreid1.com/bots/b-captain-hook">https://git.charlesreid1.com/bots/b-captain-hook</a> or |
||||
<a href="https://github.com/charlesreid1/captain-hook">https://github.com/charlesreid1/captain-hook</a>), it creates a |
||||
trigger file.</p> |
||||
<p>Meanwhile, on the host that is running the docker pod, a service |
||||
script is running continuously to check for that trigger file |
||||
every 10 seconds. If the trigger file is seen, it updates the |
||||
Captain Hook git repository on the host machine and then restarts |
||||
the docker pod.</p> |
||||
<p>Sections below cover the following scripts, all run on the host:</p> |
||||
<ul> |
||||
<li>The canary bash script</li> |
||||
<li>The docker host pull script</li> |
||||
<li>The canary statup service</li> |
||||
</ul> |
||||
<h2 id="the-canary-bash-script">The Canary Bash Script<a class="headerlink" href="#the-canary-bash-script" title="Permanent link">¶</a></h2> |
||||
<p>Note: this needs an associated systemd service. |
||||
See the services directory of the dotfiles repo.</p> |
||||
<p>This is a canary script for connecting |
||||
the Captain Hook container to the host |
||||
machine, and triggering tasks on the |
||||
host machine with webhooks.</p> |
||||
<p>The Captain Hook container mounts the |
||||
following host directory inside the |
||||
container (same location for host/container):</p> |
||||
<div class="codehilite"><pre><span></span>/tmp/triggers/ |
||||
</pre></div> |
||||
|
||||
|
||||
<p>When a webhook in Captain Hook wants to |
||||
trigger an event on the host (blackbeard), |
||||
it puts a file in <code>/tmp/triggers/</code>.</p> |
||||
<p>Meanwhile, on the host, this script checks |
||||
every 10 seconds for trigger files.</p> |
||||
<p>Each webhook can create its own trigger file, |
||||
and this script processes each trigger differently.</p> |
||||
<div class="codehilite"><pre><span></span><span class="ch">#!/bin/bash</span> |
||||
|
||||
<span class="nv">TRIGGER</span><span class="o">=</span><span class="s2">"/tmp/triggers/push-b-captain-hook-master"</span> |
||||
<span class="nv">UPDATE_SCRIPT</span><span class="o">=</span><span class="s2">"</span><span class="si">${</span><span class="nv">HOME</span><span class="si">}</span><span class="s2">/pod-webhooks/scripts/captain_hook_pull_host.py"</span> |
||||
|
||||
<span class="k">while</span> <span class="nb">true</span> |
||||
<span class="k">do</span> |
||||
<span class="c1"># bootstrap-pull captain hook</span> |
||||
<span class="k">if</span> <span class="o">[</span> -f <span class="s2">"</span><span class="nv">$TRIGGER</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> |
||||
<span class="nb">echo</span> <span class="s2">"CAPTAIN HOOK'S CANARY:"</span> |
||||
<span class="nb">echo</span> <span class="s2">"Running trigger to update Captain Hook on the host machine (user charles)"</span> |
||||
sudo -H -u charles python <span class="nv">$UPDATE_SCRIPT</span> |
||||
<span class="nb">echo</span> <span class="s2">"All done."</span> |
||||
rm -f <span class="si">${</span><span class="nv">TRIGGER</span><span class="si">}</span> |
||||
<span class="k">fi</span> |
||||
|
||||
sleep <span class="m">10</span><span class="p">;</span> |
||||
<span class="k">done</span> |
||||
</pre></div> |
||||
|
||||
|
||||
<h2 id="the-pull-host-captain-hook-script">The Pull Host Captain Hook Script<a class="headerlink" href="#the-pull-host-captain-hook-script" title="Permanent link">¶</a></h2> |
||||
<p>Next we have a python script that actually updates the host's |
||||
version of Captain Hook:</p> |
||||
<div class="codehilite"><pre><span></span><span class="ch">#!/usr/bin/env python3</span> |
||||
<span class="kn">import</span> <span class="nn">subprocess</span> |
||||
<span class="kn">import</span> <span class="nn">os</span> |
||||
<span class="kn">import</span> <span class="nn">time</span> |
||||
|
||||
<span class="sd">"""</span> |
||||
<span class="sd">Captain Hook: Pull Captain Hook on the Host </span> |
||||
|
||||
<span class="sd">This script is called by the host machine </span> |
||||
<span class="sd">(blackbeard) running the Captain Hook container.</span> |
||||
|
||||
<span class="sd">This is triggered by push actions to the </span> |
||||
<span class="sd">master branch of b-captain-hook.</span> |
||||
|
||||
<span class="sd">The action is to update (git pull) the copy </span> |
||||
<span class="sd">of Captain Hook running on the host, and</span> |
||||
<span class="sd">restart the container pod.</span> |
||||
<span class="sd">"""</span> |
||||
|
||||
<span class="n">work_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">'/home'</span><span class="p">,</span><span class="s1">'charles'</span><span class="p">,</span><span class="s1">'pod-webhooks'</span><span class="p">,</span><span class="s1">'b-captain-hook'</span><span class="p">)</span> |
||||
|
||||
<span class="c1"># Step 1:</span> |
||||
<span class="c1"># Update Captain Hook</span> |
||||
<span class="n">pull_cmd</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'git'</span><span class="p">,</span><span class="s1">'pull'</span><span class="p">,</span><span class="s1">'origin'</span><span class="p">,</span><span class="s1">'master'</span><span class="p">]</span> |
||||
<span class="n">subprocess</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">pull_cmd</span><span class="p">,</span> <span class="n">cwd</span><span class="o">=</span><span class="n">work_dir</span><span class="p">)</span> |
||||
|
||||
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> |
||||
|
||||
<span class="c1"># Step 2:</span> |
||||
<span class="c1"># Restart Captain Hook pod</span> |
||||
<span class="n">pod_restart</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'docker-compose'</span><span class="p">,</span><span class="s1">'restart'</span><span class="p">]</span> |
||||
<span class="n">subprocess</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">pod_restart</span><span class="p">,</span> <span class="n">cwd</span><span class="o">=</span><span class="n">work_dir</span><span class="p">)</span> |
||||
</pre></div> |
||||
|
||||
|
||||
<h2 id="the-canary-startup-script">The Canary Startup Script<a class="headerlink" href="#the-canary-startup-script" title="Permanent link">¶</a></h2> |
||||
<p>Here is the startup file that runs the Captain Hook's Canary bash script.</p> |
||||
<p>The stop directive uses pgrep to find the process id and stops any PIDs returned.</p> |
||||
<div class="codehilite"><pre><span></span>[Unit] |
||||
Description=captain hook canary script |
||||
Requires=pod-webhooks.service |
||||
After=pod-webhooks.service |
||||
|
||||
[Service] |
||||
Restart=always |
||||
ExecStart=/home/charles/pod-webhooks/scripts/captain_hook_canary.sh |
||||
ExecStop=/usr/bin/pgrep -f captain_hook_canary | /usr/bin/xargs /bin/kill |
||||
|
||||
[Install] |
||||
WantedBy=default.target |
||||
</pre></div> |
||||
|
||||
|
||||
<p>See <a href="../services/">Services</a> for more info on what to do with this file.</p> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article> |
||||
</div> |
||||
</div> |
||||
</main> |
||||
|
||||
|
||||
<footer class="md-footer"> |
||||
|
||||
<div class="md-footer-nav"> |
||||
<nav class="md-footer-nav__inner md-grid"> |
||||
|
||||
<a href="../services/" title="Captain Hook Startup Services" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev"> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"> |
||||
<span class="md-flex__ellipsis"> |
||||
<span class="md-footer-nav__direction"> |
||||
Previous |
||||
</span> |
||||
Captain Hook Startup Services |
||||
</span> |
||||
</div> |
||||
</a> |
||||
|
||||
|
||||
</nav> |
||||
</div> |
||||
|
||||
<div class="md-footer-meta md-typeset"> |
||||
<div class="md-footer-meta__inner md-grid"> |
||||
<div class="md-footer-copyright"> |
||||
|
||||
<div class="md-footer-copyright__highlight"> |
||||
Copyright © 2018 <a href="https://charlesreid1.com">Charles Reid</a>, released under the <a href="https://opensource.org/licenses/MIT">MIT license</a> |
||||
</div> |
||||
|
||||
powered by |
||||
<a href="https://www.mkdocs.org">MkDocs</a> |
||||
and |
||||
<a href="https://squidfunk.github.io/mkdocs-material/"> |
||||
Material for MkDocs</a> |
||||
</div> |
||||
|
||||
|
||||
|
||||
</div> |
||||
</div> |
||||
</footer> |
||||
|
||||
</div> |
||||
|
||||
<script src="../assets/javascripts/application.e72fd936.js"></script> |
||||
|
||||
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script> |
||||
|
||||
<script src="../search/main.js"></script> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</body> |
||||
</html> |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2018 Charles Reid |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
# pod-webhooks |
||||
|
||||
This docker pod runs two services: |
||||
|
||||
* Captain Hook webhook server (python + flask) |
||||
* [b-captain-hook](https://git.charlesreid1.com/bots/b-captain-hook) |
||||
* Static content server for subdomain pages (nginx) |
||||
* [d-nginx-subdomains](https://git.charlesreid1.com/docker/d-nginx-subdomains) |
||||
|
||||
These two services are in this repo as submodules. |
||||
|
||||
|
||||
## Links |
||||
|
||||
See documentation page here: <https://pages.charlesreid1.com/pod-webhooks> |
||||
|
||||
Or visit [docs/index.md](/docs/index.md) |
||||
|
||||
Source code on git.charlesreid1.com: <https://git.charlesreid1.com/docker/pod-webhooks> |
||||
|
||||
Source code on github.com: <https://github.com/charlesreid1-docker/pod-webhooks> |
||||
|
||||
|
||||
## If you get a 403 |
||||
|
||||
If you visit the IP of the page running things and you get a 403, |
||||
it's probably because you haven't created the `/www/` directory |
||||
structure yet. |
||||
|
||||
To do this, you need a folder for each subdomain at `/www/`, along |
||||
with subdirectories for `htdocs` and for the `.git` directory |
||||
(see `scripts/` directory for scripts to do this automatically): |
||||
|
||||
``` |
||||
/www/pages.charlesreid1.com/ |
||||
/www/bots.charlesreid1.com/ |
||||
/www/hooks.charlesreid1.com/ |
||||
``` |
||||
|
||||
|
@ -1,513 +0,0 @@
@@ -1,513 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html> |
||||
<html lang="en" class="no-js"> |
||||
<head> |
||||
|
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width,initial-scale=1"> |
||||
<meta http-equiv="x-ua-compatible" content="ie=edge"> |
||||
|
||||
|
||||
<link rel="canonical" href="https://pages.charlesreid1.com/pod-webhooks/running/"> |
||||
|
||||
|
||||
|
||||
<meta name="lang:clipboard.copy" content="Copy to clipboard"> |
||||
|
||||
<meta name="lang:clipboard.copied" content="Copied to clipboard"> |
||||
|
||||
<meta name="lang:search.language" content="en"> |
||||
|
||||
<meta name="lang:search.pipeline.stopwords" content="True"> |
||||
|
||||
<meta name="lang:search.pipeline.trimmer" content="True"> |
||||
|
||||
<meta name="lang:search.result.none" content="No matching documents"> |
||||
|
||||
<meta name="lang:search.result.one" content="1 matching document"> |
||||
|
||||
<meta name="lang:search.result.other" content="# matching documents"> |
||||
|
||||
<meta name="lang:search.tokenizer" content="[\s\-]+"> |
||||
|
||||
<link rel="shortcut icon" href=".."> |
||||
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-3.0.3"> |
||||
|
||||
|
||||
|
||||
<title>Running Captain Hook - pod-webhooks</title> |
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/application.451f80e5.css"> |
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/application-palette.22915126.css"> |
||||
|
||||
|
||||
|
||||
|
||||
<meta name="theme-color" content="#2196f3"> |
||||
|
||||
|
||||
|
||||
<script src="../assets/javascripts/modernizr.1aa3b519.js"></script> |
||||
|
||||
|
||||
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin> |
||||
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono"> |
||||
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style> |
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/fonts/material-icons.css"> |
||||
|
||||
<link rel="stylesheet" href="../css/custom.css"> |
||||
|
||||
|
||||
</head> |
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-primary="blue" data-md-color-accent="blue"> |
||||
|
||||
<svg class="md-svg"> |
||||
<defs> |
||||
|
||||
|
||||
</defs> |
||||
</svg> |
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off"> |
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> |
||||
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label> |
||||
|
||||
<a href="../#the-docker-compose-file" tabindex="1" class="md-skip"> |
||||
Skip to content |
||||
</a> |
||||
|
||||
|
||||
<header class="md-header" data-md-component="header"> |
||||
<nav class="md-header-nav md-grid"> |
||||
<div class="md-flex"> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<a href="https://pages.charlesreid1.com/pod-webhooks" title="pod-webhooks" class="md-header-nav__button md-logo"> |
||||
|
||||
<i class="md-icon">dns</i> |
||||
|
||||
</a> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--stretch"> |
||||
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title"> |
||||
|
||||
|
||||
<span class="md-header-nav__topic"> |
||||
pod-webhooks |
||||
</span> |
||||
<span class="md-header-nav__topic"> |
||||
Running Captain Hook |
||||
</span> |
||||
|
||||
|
||||
</div> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
|
||||
|
||||
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label> |
||||
|
||||
<div class="md-search" data-md-component="search" role="dialog"> |
||||
<label class="md-search__overlay" for="__search"></label> |
||||
<div class="md-search__inner" role="search"> |
||||
<form class="md-search__form" name="search"> |
||||
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active"> |
||||
<label class="md-icon md-search__icon" for="__search"></label> |
||||
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1"> |
||||
 |
||||
</button> |
||||
</form> |
||||
<div class="md-search__output"> |
||||
<div class="md-search__scrollwrap" data-md-scrollfix> |
||||
<div class="md-search-result" data-md-component="result"> |
||||
<div class="md-search-result__meta"> |
||||
Type to start searching |
||||
</div> |
||||
<ol class="md-search-result__list"></ol> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
</div> |
||||
|
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<div class="md-header-nav__source"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://git.charlesreid1.com/docker/pod-webhooks" title="Go to repository" class="md-source" data-md-source=""> |
||||
|
||||
<div class="md-source__repository"> |
||||
pod-webhooks |
||||
</div> |
||||
</a> |
||||
|
||||
</div> |
||||
</div> |
||||
|
||||
</div> |
||||
</nav> |
||||
</header> |
||||
|
||||
<div class="md-container"> |
||||
|
||||
|
||||
|
||||
<main class="md-main"> |
||||
<div class="md-main__inner md-grid" data-md-component="container"> |
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation"> |
||||
<div class="md-sidebar__scrollwrap"> |
||||
<div class="md-sidebar__inner"> |
||||
<nav class="md-nav md-nav--primary" data-md-level="0"> |
||||
<label class="md-nav__title md-nav__title--site" for="__drawer"> |
||||
<a href="https://pages.charlesreid1.com/pod-webhooks" title="pod-webhooks" class="md-nav__button md-logo"> |
||||
|
||||
<i class="md-icon">dns</i> |
||||
|
||||
</a> |
||||
pod-webhooks |
||||
</label> |
||||
|
||||
<div class="md-nav__source"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://git.charlesreid1.com/docker/pod-webhooks" title="Go to repository" class="md-source" data-md-source=""> |
||||
|
||||
<div class="md-source__repository"> |
||||
pod-webhooks |
||||
</div> |
||||
</a> |
||||
|
||||
</div> |
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href=".." title="Home" class="md-nav__link"> |
||||
Home |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../adding/" title="Adding Webhooks" class="md-nav__link"> |
||||
Adding Webhooks |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--active"> |
||||
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc"> |
||||
|
||||
|
||||
<label class="md-nav__link md-nav__link--active" for="__toc"> |
||||
Running Captain Hook |
||||
</label> |
||||
|
||||
<a href="./" title="Running Captain Hook" class="md-nav__link md-nav__link--active"> |
||||
Running Captain Hook |
||||
</a> |
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary"> |
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#the-docker-compose-file" title="The Docker Compose File" class="md-nav__link"> |
||||
The Docker Compose File |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#running-webhooks-docker-pod-from-command-line" title="Running Webhooks Docker Pod from Command Line" class="md-nav__link"> |
||||
Running Webhooks Docker Pod from Command Line |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#workflow-for-docker-pod-updates" title="Workflow for Docker Pod Updates" class="md-nav__link"> |
||||
Workflow for Docker Pod Updates |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul> |
||||
|
||||
</nav> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../services/" title="Captain Hook Startup Services" class="md-nav__link"> |
||||
Captain Hook Startup Services |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../canary/" title="Captain Hook's Canary" class="md-nav__link"> |
||||
Captain Hook's Canary |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
</ul> |
||||
</nav> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc"> |
||||
<div class="md-sidebar__scrollwrap"> |
||||
<div class="md-sidebar__inner"> |
||||
|
||||
<nav class="md-nav md-nav--secondary"> |
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#the-docker-compose-file" title="The Docker Compose File" class="md-nav__link"> |
||||
The Docker Compose File |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#running-webhooks-docker-pod-from-command-line" title="Running Webhooks Docker Pod from Command Line" class="md-nav__link"> |
||||
Running Webhooks Docker Pod from Command Line |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#workflow-for-docker-pod-updates" title="Workflow for Docker Pod Updates" class="md-nav__link"> |
||||
Workflow for Docker Pod Updates |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul> |
||||
|
||||
</nav> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<div class="md-content"> |
||||
<article class="md-content__inner md-typeset"> |
||||
|
||||
|
||||
|
||||
<h1>Running Captain Hook</h1> |
||||
|
||||
<h2 id="the-docker-compose-file">The Docker Compose File<a class="headerlink" href="#the-docker-compose-file" title="Permanent link">¶</a></h2> |
||||
<p>The <code>docker-compose.yml</code> file contains everything needed to |
||||
run the webhooks docker pod: a Captain Hook webhook server, and |
||||
an nginx server to serve up static pages for each subdomain.</p> |
||||
<p>Why use docker-compose instead of docker? |
||||
docker-compose is the preferred way to run multiple containers.</p> |
||||
<h2 id="running-webhooks-docker-pod-from-command-line">Running Webhooks Docker Pod from Command Line<a class="headerlink" href="#running-webhooks-docker-pod-from-command-line" title="Permanent link">¶</a></h2> |
||||
<p>Run the pod in the foreground or background by running these |
||||
commands from the directory containing <code>docker-compose.yml</code>:</p> |
||||
<div class="codehilite"><pre><span></span>docker-compose up # interactive |
||||
docker-compose up -d # detached |
||||
</pre></div> |
||||
|
||||
|
||||
<p>If you want to rebuild all the containers before bringing |
||||
the pod up, add the <code>--build</code> flag:</p> |
||||
<div class="codehilite"><pre><span></span>docker-compose up --build |
||||
</pre></div> |
||||
|
||||
|
||||
<p>If you just want to rebuild the containers without bringing |
||||
them up,</p> |
||||
<div class="codehilite"><pre><span></span>docker-compose build |
||||
</pre></div> |
||||
|
||||
|
||||
<p>To rebuild absolutely everything from scratch,</p> |
||||
<div class="codehilite"><pre><span></span>docker-compose build --no-cache |
||||
</pre></div> |
||||
|
||||
|
||||
<p><strong><em>WARNING:</em></strong> this will re-download all aptitude packages, |
||||
which can be extremely slow. Use with caution.</p> |
||||
<p>You can restart all containers in a pod using the restart command:</p> |
||||
<div class="codehilite"><pre><span></span>docker-compose restart |
||||
</pre></div> |
||||
|
||||
|
||||
<p><strong><em>WARNING:</em></strong> this will <strong><em>NOT</em></strong> pick up changes to |
||||
Dockerfiles or to files that are mounted into the container. |
||||
This simply restarts the container using the same image |
||||
(in memory) that was previously running, <strong><em>without</em></strong> |
||||
getting an up-to-date container image.</p> |
||||
<h2 id="workflow-for-docker-pod-updates">Workflow for Docker Pod Updates<a class="headerlink" href="#workflow-for-docker-pod-updates" title="Permanent link">¶</a></h2> |
||||
<p>To minimize downtime, use the following workflow:</p> |
||||
<ul> |
||||
<li>Run <code>docker-compose build</code> to rebuild the images, leaving the pod running (they are not affected)</li> |
||||
<li>Run <code>docker-compose down</code> to bring the pod down</li> |
||||
<li>Run <code>docker-compose up</code> to bring the pod up</li> |
||||
</ul> |
||||
<p>(Add the <code>-d</code> flag to start the docker pod in the background.)</p> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article> |
||||
</div> |
||||
</div> |
||||
</main> |
||||
|
||||
|
||||
<footer class="md-footer"> |
||||
|
||||
<div class="md-footer-nav"> |
||||
<nav class="md-footer-nav__inner md-grid"> |
||||
|
||||
<a href="../adding/" title="Adding Webhooks" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev"> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"> |
||||
<span class="md-flex__ellipsis"> |
||||
<span class="md-footer-nav__direction"> |
||||
Previous |
||||
</span> |
||||
Adding Webhooks |
||||
</span> |
||||
</div> |
||||
</a> |
||||
|
||||
|
||||
<a href="../services/" title="Captain Hook Startup Services" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next"> |
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"> |
||||
<span class="md-flex__ellipsis"> |
||||
<span class="md-footer-nav__direction"> |
||||
Next |
||||
</span> |
||||
Captain Hook Startup Services |
||||
</span> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i> |
||||
</div> |
||||
</a> |
||||
|
||||
</nav> |
||||
</div> |
||||
|
||||
<div class="md-footer-meta md-typeset"> |
||||
<div class="md-footer-meta__inner md-grid"> |
||||
<div class="md-footer-copyright"> |
||||
|
||||
<div class="md-footer-copyright__highlight"> |
||||
Copyright © 2018 <a href="https://charlesreid1.com">Charles Reid</a>, released under the <a href="https://opensource.org/licenses/MIT">MIT license</a> |
||||
</div> |
||||
|
||||
powered by |
||||
<a href="https://www.mkdocs.org">MkDocs</a> |
||||
and |
||||
<a href="https://squidfunk.github.io/mkdocs-material/"> |
||||
Material for MkDocs</a> |
||||
</div> |
||||
|
||||
|
||||
|
||||
</div> |
||||
</div> |
||||
</footer> |
||||
|
||||
</div> |
||||
|
||||
<script src="../assets/javascripts/application.e72fd936.js"></script> |
||||
|
||||
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script> |
||||
|
||||
<script src="../search/main.js"></script> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</body> |
||||
</html> |
@ -1,568 +0,0 @@
@@ -1,568 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html> |
||||
<html lang="en" class="no-js"> |
||||
<head> |
||||
|
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width,initial-scale=1"> |
||||
<meta http-equiv="x-ua-compatible" content="ie=edge"> |
||||
|
||||
|
||||
<link rel="canonical" href="https://pages.charlesreid1.com/pod-webhooks/services/"> |
||||
|
||||
|
||||
|
||||
<meta name="lang:clipboard.copy" content="Copy to clipboard"> |
||||
|
||||
<meta name="lang:clipboard.copied" content="Copied to clipboard"> |
||||
|
||||
<meta name="lang:search.language" content="en"> |
||||
|
||||
<meta name="lang:search.pipeline.stopwords" content="True"> |
||||
|
||||
<meta name="lang:search.pipeline.trimmer" content="True"> |
||||
|
||||
<meta name="lang:search.result.none" content="No matching documents"> |
||||
|
||||
<meta name="lang:search.result.one" content="1 matching document"> |
||||
|
||||
<meta name="lang:search.result.other" content="# matching documents"> |
||||
|
||||
<meta name="lang:search.tokenizer" content="[\s\-]+"> |
||||
|
||||
<link rel="shortcut icon" href=".."> |
||||
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-3.0.3"> |
||||
|
||||
|
||||
|
||||
<title>Captain Hook Startup Services - pod-webhooks</title> |
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/application.451f80e5.css"> |
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/application-palette.22915126.css"> |
||||
|
||||
|
||||
|
||||
|
||||
<meta name="theme-color" content="#2196f3"> |
||||
|
||||
|
||||
|
||||
<script src="../assets/javascripts/modernizr.1aa3b519.js"></script> |
||||
|
||||
|
||||
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin> |
||||
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono"> |
||||
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style> |
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/fonts/material-icons.css"> |
||||
|
||||
<link rel="stylesheet" href="../css/custom.css"> |
||||
|
||||
|
||||
</head> |
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-primary="blue" data-md-color-accent="blue"> |
||||
|
||||
<svg class="md-svg"> |
||||
<defs> |
||||
|
||||
|
||||
</defs> |
||||
</svg> |
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off"> |
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> |
||||
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label> |
||||
|
||||
<a href="../#running-hooks-subdomains-docker-pod-as-startup-service" tabindex="1" class="md-skip"> |
||||
Skip to content |
||||
</a> |
||||
|
||||
|
||||
<header class="md-header" data-md-component="header"> |
||||
<nav class="md-header-nav md-grid"> |
||||
<div class="md-flex"> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<a href="https://pages.charlesreid1.com/pod-webhooks" title="pod-webhooks" class="md-header-nav__button md-logo"> |
||||
|
||||
<i class="md-icon">dns</i> |
||||
|
||||
</a> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--stretch"> |
||||
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title"> |
||||
|
||||
|
||||
<span class="md-header-nav__topic"> |
||||
pod-webhooks |
||||
</span> |
||||
<span class="md-header-nav__topic"> |
||||
Captain Hook Startup Services |
||||
</span> |
||||
|
||||
|
||||
</div> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
|
||||
|
||||
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label> |
||||
|
||||
<div class="md-search" data-md-component="search" role="dialog"> |
||||
<label class="md-search__overlay" for="__search"></label> |
||||
<div class="md-search__inner" role="search"> |
||||
<form class="md-search__form" name="search"> |
||||
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active"> |
||||
<label class="md-icon md-search__icon" for="__search"></label> |
||||
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1"> |
||||
 |
||||
</button> |
||||
</form> |
||||
<div class="md-search__output"> |
||||
<div class="md-search__scrollwrap" data-md-scrollfix> |
||||
<div class="md-search-result" data-md-component="result"> |
||||
<div class="md-search-result__meta"> |
||||
Type to start searching |
||||
</div> |
||||
<ol class="md-search-result__list"></ol> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
</div> |
||||
|
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<div class="md-header-nav__source"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://git.charlesreid1.com/docker/pod-webhooks" title="Go to repository" class="md-source" data-md-source=""> |
||||
|
||||
<div class="md-source__repository"> |
||||
pod-webhooks |
||||
</div> |
||||
</a> |
||||
|
||||
</div> |
||||
</div> |
||||
|
||||
</div> |
||||
</nav> |
||||
</header> |
||||
|
||||
<div class="md-container"> |
||||
|
||||
|
||||
|
||||
<main class="md-main"> |
||||
<div class="md-main__inner md-grid" data-md-component="container"> |
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation"> |
||||
<div class="md-sidebar__scrollwrap"> |
||||
<div class="md-sidebar__inner"> |
||||
<nav class="md-nav md-nav--primary" data-md-level="0"> |
||||
<label class="md-nav__title md-nav__title--site" for="__drawer"> |
||||
<a href="https://pages.charlesreid1.com/pod-webhooks" title="pod-webhooks" class="md-nav__button md-logo"> |
||||
|
||||
<i class="md-icon">dns</i> |
||||
|
||||
</a> |
||||
pod-webhooks |
||||
</label> |
||||
|
||||
<div class="md-nav__source"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://git.charlesreid1.com/docker/pod-webhooks" title="Go to repository" class="md-source" data-md-source=""> |
||||
|
||||
<div class="md-source__repository"> |
||||
pod-webhooks |
||||
</div> |
||||
</a> |
||||
|
||||
</div> |
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href=".." title="Home" class="md-nav__link"> |
||||
Home |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../adding/" title="Adding Webhooks" class="md-nav__link"> |
||||
Adding Webhooks |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../running/" title="Running Captain Hook" class="md-nav__link"> |
||||
Running Captain Hook |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--active"> |
||||
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc"> |
||||
|
||||
|
||||
<label class="md-nav__link md-nav__link--active" for="__toc"> |
||||
Captain Hook Startup Services |
||||
</label> |
||||
|
||||
<a href="./" title="Captain Hook Startup Services" class="md-nav__link md-nav__link--active"> |
||||
Captain Hook Startup Services |
||||
</a> |
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary"> |
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#running-hooks-subdomains-docker-pod-as-startup-service" title="Running Hooks-Subdomains Docker Pod as Startup Service" class="md-nav__link"> |
||||
Running Hooks-Subdomains Docker Pod as Startup Service |
||||
</a> |
||||
|
||||
<nav class="md-nav"> |
||||
<ul class="md-nav__list"> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#docker-pod-startup-service" title="Docker Pod Startup Service" class="md-nav__link"> |
||||
Docker Pod Startup Service |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#captain-hooks-canary-startup-service" title="Captain Hook's Canary Startup Service" class="md-nav__link"> |
||||
Captain Hook's Canary Startup Service |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#installing-services" title="Installing Services" class="md-nav__link"> |
||||
Installing Services |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
</ul> |
||||
</nav> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul> |
||||
|
||||
</nav> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="../canary/" title="Captain Hook's Canary" class="md-nav__link"> |
||||
Captain Hook's Canary |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
</ul> |
||||
</nav> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc"> |
||||
<div class="md-sidebar__scrollwrap"> |
||||
<div class="md-sidebar__inner"> |
||||
|
||||
<nav class="md-nav md-nav--secondary"> |
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#running-hooks-subdomains-docker-pod-as-startup-service" title="Running Hooks-Subdomains Docker Pod as Startup Service" class="md-nav__link"> |
||||
Running Hooks-Subdomains Docker Pod as Startup Service |
||||
</a> |
||||
|
||||
<nav class="md-nav"> |
||||
<ul class="md-nav__list"> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#docker-pod-startup-service" title="Docker Pod Startup Service" class="md-nav__link"> |
||||
Docker Pod Startup Service |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#captain-hooks-canary-startup-service" title="Captain Hook's Canary Startup Service" class="md-nav__link"> |
||||
Captain Hook's Canary Startup Service |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#installing-services" title="Installing Services" class="md-nav__link"> |
||||
Installing Services |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
</ul> |
||||
</nav> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul> |
||||
|
||||
</nav> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<div class="md-content"> |
||||
<article class="md-content__inner md-typeset"> |
||||
|
||||
|
||||
|
||||
<h1>Captain Hook Startup Services</h1> |
||||
|
||||
<h2 id="running-hooks-subdomains-docker-pod-as-startup-service">Running Hooks-Subdomains Docker Pod as Startup Service<a class="headerlink" href="#running-hooks-subdomains-docker-pod-as-startup-service" title="Permanent link">¶</a></h2> |
||||
<p>The webhooks-subdomains docker pod requires two startup |
||||
services:</p> |
||||
<ul> |
||||
<li> |
||||
<p>Docker pod service - this startup service keeps the pod running, |
||||
and will restart it if it crashes</p> |
||||
</li> |
||||
<li> |
||||
<p>Captain Hook's canary - this watches a folder that is shared between |
||||
the docker pod host and the Captain Hook container, which allows the |
||||
pod to send triggers to the host.</p> |
||||
</li> |
||||
</ul> |
||||
<p>Also see the <code>scripts/</code> folder of this repo, |
||||
<a href="https://git.charlesreid1.com/docker/pod-webhooks">pod-webhooks</a> |
||||
(<a href="https://github.com/charlesreid1-docker/pod-webhooks">Github mirror</a>).</p> |
||||
<h3 id="docker-pod-startup-service">Docker Pod Startup Service<a class="headerlink" href="#docker-pod-startup-service" title="Permanent link">¶</a></h3> |
||||
<p>This service keeps the webhooks docker pod service running |
||||
continuously. If the pod stops, this service will restart it.</p> |
||||
<p>(This service should not be running if you are troubleshooting |
||||
the docker pod, otherwise every time you try and stop the pod |
||||
it will respawn.)</p> |
||||
<p><strong><code>pod-webhooks.service:</code></strong></p> |
||||
<div class="codehilite"><pre><span></span>[Unit] |
||||
Description=webhooks and subdomains docker pod |
||||
Requires=docker.service |
||||
After=docker.service |
||||
|
||||
[Service] |
||||
Restart=always |
||||
ExecStart=/usr/local/bin/docker-compose -f /home/charles/codes/docker/pod-webhooks/docker-compose.yml up |
||||
ExecStop=/usr/local/bin/docker-compose -f /home/charles/codes/docker/pod-webhooks/docker-compose.yml down |
||||
|
||||
[Install] |
||||
WantedBy=default.target |
||||
</pre></div> |
||||
|
||||
|
||||
<h3 id="captain-hooks-canary-startup-service">Captain Hook's Canary Startup Service<a class="headerlink" href="#captain-hooks-canary-startup-service" title="Permanent link">¶</a></h3> |
||||
<p>This service just watches a folder for a particular |
||||
watchfile, and runs a script if it sees the watchfile |
||||
appear.</p> |
||||
<p><strong><code>captain-hook-canary.service:</code></strong></p> |
||||
<div class="codehilite"><pre><span></span>[Unit] |
||||
Description=captain hook canary script |
||||
Requires=pod-webhooks.service |
||||
After=pod-webhooks.service |
||||
|
||||
[Service] |
||||
Restart=always |
||||
ExecStart=/home/charles/pod-webhooks/scripts/captain_hook_canary.sh |
||||
ExecStop=/usr/bin/pgrep -f captain_hook_canary | /usr/bin/xargs /bin/kill |
||||
|
||||
[Install] |
||||
WantedBy=default.target |
||||
</pre></div> |
||||
|
||||
|
||||
<h3 id="installing-services">Installing Services<a class="headerlink" href="#installing-services" title="Permanent link">¶</a></h3> |
||||
<p>Install the services by copying the <code>*.service</code> files |
||||
to <code>/etc/systemd/system/dockerpod-webhooks.servce</code> |
||||
and <code>/etc/systemd/system/captain-hook-canary.servce</code>, |
||||
and activate the startup services:</p> |
||||
<div class="codehilite"><pre><span></span>sudo systemctl enable pod-webhooks.service |
||||
|
||||
sudo systemctl enable captain-hook-canary.service |
||||
</pre></div> |
||||
|
||||
|
||||
<p>Now you can start/stop the services with:</p> |
||||
<div class="codehilite"><pre><span></span>sudo systemctl (start|stop) pod-webhooks.service |
||||
|
||||
sudo systemctl (start|stop) captain-hook-canary.service |
||||
</pre></div> |
||||
|
||||
|
||||
<p>As mentioned above, these services should be stopped before |
||||
doing a <code>docker-compose stop</code> or a <code>docker-compose up --build</code> |
||||
to keep the pod from respawning in the middle of the task.</p> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article> |
||||
</div> |
||||
</div> |
||||
</main> |
||||
|
||||
|
||||
<footer class="md-footer"> |
||||
|
||||
<div class="md-footer-nav"> |
||||
<nav class="md-footer-nav__inner md-grid"> |
||||
|
||||
<a href="../running/" title="Running Captain Hook" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev"> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"> |
||||
<span class="md-flex__ellipsis"> |
||||
<span class="md-footer-nav__direction"> |
||||
Previous |
||||
</span> |
||||
Running Captain Hook |
||||
</span> |
||||
</div> |
||||
</a> |
||||
|
||||
|
||||
<a href="../canary/" title="Captain Hook's Canary" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next"> |
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"> |
||||
<span class="md-flex__ellipsis"> |
||||
<span class="md-footer-nav__direction"> |
||||
Next |
||||
</span> |
||||
Captain Hook's Canary |
||||
</span> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i> |
||||
</div> |
||||
</a> |
||||
|
||||
</nav> |
||||
</div> |
||||
|
||||
<div class="md-footer-meta md-typeset"> |
||||
<div class="md-footer-meta__inner md-grid"> |
||||
<div class="md-footer-copyright"> |
||||
|
||||
<div class="md-footer-copyright__highlight"> |
||||
Copyright © 2018 <a href="https://charlesreid1.com">Charles Reid</a>, released under the <a href="https://opensource.org/licenses/MIT">MIT license</a> |
||||
</div> |
||||
|
||||
powered by |
||||
<a href="https://www.mkdocs.org">MkDocs</a> |
||||
and |
||||
<a href="https://squidfunk.github.io/mkdocs-material/"> |
||||
Material for MkDocs</a> |
||||
</div> |
||||
|
||||
|
||||
|
||||
</div> |
||||
</div> |
||||
</footer> |
||||
|
||||
</div> |
||||
|
||||
<script src="../assets/javascripts/application.e72fd936.js"></script> |
||||
|
||||
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script> |
||||
|
||||
<script src="../search/main.js"></script> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</body> |
||||
</html> |
File diff suppressed because one or more lines are too long
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
/*! |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not |
||||
* use this file except in compliance with the License. You may obtain a copy |
||||
* of the License at: |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE |
||||
* DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. |
||||
* SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND |
||||
* LIMITATIONS UNDER THE LICENSE. |
||||
*/@font-face{font-family:"Material Icons";font-style:normal;font-weight:400;src:local("Material Icons"),local("MaterialIcons-Regular"),url("specimen/MaterialIcons-Regular.woff2") format("woff2"),url("specimen/MaterialIcons-Regular.woff") format("woff"),url("specimen/MaterialIcons-Regular.ttf") format("truetype")} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 521 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.6 KiB |
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,i,n;e.da=function(){this.pipeline.reset(),this.pipeline.add(e.da.trimmer,e.da.stopWordFilter,e.da.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.da.stemmer))},e.da.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.da.trimmer=e.trimmerSupport.generateTrimmer(e.da.wordCharacters),e.Pipeline.registerFunction(e.da.trimmer,"trimmer-da"),e.da.stemmer=(r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){var e,n,t,s=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],o=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],a=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],u=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],c=new i;function l(){var e,r=c.limit-c.cursor;c.cursor>=n&&(e=c.limit_backward,c.limit_backward=n,c.ket=c.cursor,c.find_among_b(o,4)?(c.bra=c.cursor,c.limit_backward=e,c.cursor=c.limit-r,c.cursor>c.limit_backward&&(c.cursor--,c.bra=c.cursor,c.slice_del())):c.limit_backward=e)}this.setCurrent=function(e){c.setCurrent(e)},this.getCurrent=function(){return c.getCurrent()},this.stem=function(){var r,i=c.cursor;return function(){var r,i=c.cursor+3;if(n=c.limit,0<=i&&i<=c.limit){for(e=i;;){if(r=c.cursor,c.in_grouping(d,97,248)){c.cursor=r;break}if(c.cursor=r,r>=c.limit)return;c.cursor++}for(;!c.out_grouping(d,97,248);){if(c.cursor>=c.limit)return;c.cursor++}(n=c.cursor)<e&&(n=e)}}(),c.limit_backward=i,c.cursor=c.limit,function(){var e,r;if(c.cursor>=n&&(r=c.limit_backward,c.limit_backward=n,c.ket=c.cursor,e=c.find_among_b(s,32),c.limit_backward=r,e))switch(c.bra=c.cursor,e){case 1:c.slice_del();break;case 2:c.in_grouping_b(u,97,229)&&c.slice_del()}}(),c.cursor=c.limit,l(),c.cursor=c.limit,function(){var e,r,i,t=c.limit-c.cursor;if(c.ket=c.cursor,c.eq_s_b(2,"st")&&(c.bra=c.cursor,c.eq_s_b(2,"ig")&&c.slice_del()),c.cursor=c.limit-t,c.cursor>=n&&(r=c.limit_backward,c.limit_backward=n,c.ket=c.cursor,e=c.find_among_b(a,5),c.limit_backward=r,e))switch(c.bra=c.cursor,e){case 1:c.slice_del(),i=c.limit-c.cursor,l(),c.cursor=c.limit-i;break;case 2:c.slice_from("løs")}}(),c.cursor=c.limit,c.cursor>=n&&(r=c.limit_backward,c.limit_backward=n,c.ket=c.cursor,c.out_grouping_b(d,97,248)?(c.bra=c.cursor,t=c.slice_to(t),c.limit_backward=r,c.eq_v_b(t)&&c.slice_del()):c.limit_backward=r),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}}); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.jp=function(){this.pipeline.reset(),this.pipeline.add(e.jp.stopWordFilter,e.jp.stemmer),r?this.tokenizer=e.jp.tokenizer:(e.tokenizer&&(e.tokenizer=e.jp.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.jp.tokenizer))};var t=new e.TinySegmenter;e.jp.tokenizer=function(n){if(!arguments.length||null==n||null==n)return[];if(Array.isArray(n))return n.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(var i=n.toString().toLowerCase().replace(/^\s+/,""),o=i.length-1;o>=0;o--)if(/\S/.test(i.charAt(o))){i=i.substring(0,o+1);break}return t.segment(i).filter(function(e){return!!e}).map(function(t){return r?new e.Token(t):t})},e.jp.stemmer=function(e){return e},e.Pipeline.registerFunction(e.jp.stemmer,"stemmer-jp"),e.jp.wordCharacters="一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Za-zA-Z0-90-9",e.jp.stopWordFilter=function(t){if(-1===e.jp.stopWordFilter.stopWords.indexOf(r?t.toString():t))return t},e.jp.stopWordFilter=e.generateStopWordFilter("これ それ あれ この その あの ここ そこ あそこ こちら どこ だれ なに なん 何 私 貴方 貴方方 我々 私達 あの人 あのかた 彼女 彼 です あります おります います は が の に を で え から まで より も どの と し それで しかし".split(" ")),e.Pipeline.registerFunction(e.jp.stopWordFilter,"stopWordFilter-jp")}}); |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
!function(e,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(e.lunr)}(this,function(){return function(e){e.multiLanguage=function(){for(var i=Array.prototype.slice.call(arguments),t=i.join("-"),r="",n=[],s=[],p=0;p<i.length;++p)"en"==i[p]?(r+="\\w",n.unshift(e.stopWordFilter),n.push(e.stemmer),s.push(e.stemmer)):(r+=e[i[p]].wordCharacters,n.unshift(e[i[p]].stopWordFilter),n.push(e[i[p]].stemmer),s.push(e[i[p]].stemmer));var o=e.trimmerSupport.generateTrimmer(r);return e.Pipeline.registerFunction(o,"lunr-multi-trimmer-"+t),n.unshift(o),function(){this.pipeline.reset(),this.pipeline.add.apply(this.pipeline,n),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add.apply(this.searchPipeline,s))}}}}); |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,n,i;e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=(r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){var e,i,t=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],o=[new r("dt",-1,-1),new r("vt",-1,-1)],s=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],a=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],m=[119,125,149,1],l=new n;this.setCurrent=function(e){l.setCurrent(e)},this.getCurrent=function(){return l.getCurrent()},this.stem=function(){var r,n,u,d,c=l.cursor;return function(){var r,n=l.cursor+3;if(i=l.limit,0<=n||n<=l.limit){for(e=n;;){if(r=l.cursor,l.in_grouping(a,97,248)){l.cursor=r;break}if(r>=l.limit)return;l.cursor=r+1}for(;!l.out_grouping(a,97,248);){if(l.cursor>=l.limit)return;l.cursor++}(i=l.cursor)<e&&(i=e)}}(),l.limit_backward=c,l.cursor=l.limit,function(){var e,r,n;if(l.cursor>=i&&(r=l.limit_backward,l.limit_backward=i,l.ket=l.cursor,e=l.find_among_b(t,29),l.limit_backward=r,e))switch(l.bra=l.cursor,e){case 1:l.slice_del();break;case 2:n=l.limit-l.cursor,l.in_grouping_b(m,98,122)?l.slice_del():(l.cursor=l.limit-n,l.eq_s_b(1,"k")&&l.out_grouping_b(a,97,248)&&l.slice_del());break;case 3:l.slice_from("er")}}(),l.cursor=l.limit,n=l.limit-l.cursor,l.cursor>=i&&(r=l.limit_backward,l.limit_backward=i,l.ket=l.cursor,l.find_among_b(o,2)?(l.bra=l.cursor,l.limit_backward=r,l.cursor=l.limit-n,l.cursor>l.limit_backward&&(l.cursor--,l.bra=l.cursor,l.slice_del())):l.limit_backward=r),l.cursor=l.limit,l.cursor>=i&&(d=l.limit_backward,l.limit_backward=i,l.ket=l.cursor,(u=l.find_among_b(s,11))?(l.bra=l.cursor,l.limit_backward=d,1==u&&l.slice_del()):l.limit_backward=d),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}}); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
!function(r,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(r.lunr)}(this,function(){return function(r){r.stemmerSupport={Among:function(r,t,i,s){if(this.toCharArray=function(r){for(var t=r.length,i=new Array(t),s=0;s<t;s++)i[s]=r.charCodeAt(s);return i},!r&&""!=r||!t&&0!=t||!i)throw"Bad Among initialisation: s:"+r+", substring_i: "+t+", result: "+i;this.s_size=r.length,this.s=this.toCharArray(r),this.substring_i=t,this.result=i,this.method=s},SnowballProgram:function(){var r;return{bra:0,ket:0,limit:0,cursor:0,limit_backward:0,setCurrent:function(t){r=t,this.cursor=0,this.limit=t.length,this.limit_backward=0,this.bra=this.cursor,this.ket=this.limit},getCurrent:function(){var t=r;return r=null,t},in_grouping:function(t,i,s){if(this.cursor<this.limit){var e=r.charCodeAt(this.cursor);if(e<=s&&e>=i&&t[(e-=i)>>3]&1<<(7&e))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&t[(e-=i)>>3]&1<<(7&e))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursor<this.limit){var e=r.charCodeAt(this.cursor);if(e>s||e<i)return this.cursor++,!0;if(!(t[(e-=i)>>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e<i)return this.cursor--,!0;if(!(t[(e-=i)>>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor<t)return!1;for(var s=0;s<t;s++)if(r.charCodeAt(this.cursor+s)!=i.charCodeAt(s))return!1;return this.cursor+=t,!0},eq_s_b:function(t,i){if(this.cursor-this.limit_backward<t)return!1;for(var s=0;s<t;s++)if(r.charCodeAt(this.cursor-t+s)!=i.charCodeAt(s))return!1;return this.cursor-=t,!0},find_among:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o<h?o:h,_=t[a],m=l;m<_.s_size;m++){if(n+l==u){f=-1;break}if(f=r.charCodeAt(n+l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){if(o>=(_=t[s]).s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o<h?o:h,_=(m=t[a]).s_size-1-l;_>=0;_--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-m.s[_])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var m;if(o>=(m=t[s]).s_size){if(this.cursor=n-m.s_size,!m.method)return m.result;var b=m.method();if(this.cursor=n-m.s_size,b)return m.result}if((s=m.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}}); |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,n,t;e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=(r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){var e,t,i=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],s=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],a=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],o=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],u=[119,127,149],m=new n;this.setCurrent=function(e){m.setCurrent(e)},this.getCurrent=function(){return m.getCurrent()},this.stem=function(){var r,n=m.cursor;return function(){var r,n=m.cursor+3;if(t=m.limit,0<=n||n<=m.limit){for(e=n;;){if(r=m.cursor,m.in_grouping(o,97,246)){m.cursor=r;break}if(m.cursor=r,m.cursor>=m.limit)return;m.cursor++}for(;!m.out_grouping(o,97,246);){if(m.cursor>=m.limit)return;m.cursor++}(t=m.cursor)<e&&(t=e)}}(),m.limit_backward=n,m.cursor=m.limit,function(){var e,r=m.limit_backward;if(m.cursor>=t&&(m.limit_backward=t,m.cursor=m.limit,m.ket=m.cursor,e=m.find_among_b(i,37),m.limit_backward=r,e))switch(m.bra=m.cursor,e){case 1:m.slice_del();break;case 2:m.in_grouping_b(u,98,121)&&m.slice_del()}}(),m.cursor=m.limit,r=m.limit_backward,m.cursor>=t&&(m.limit_backward=t,m.cursor=m.limit,m.find_among_b(s,7)&&(m.cursor=m.limit,m.ket=m.cursor,m.cursor>m.limit_backward&&(m.bra=--m.cursor,m.slice_del())),m.limit_backward=r),m.cursor=m.limit,function(){var e,r;if(m.cursor>=t){if(r=m.limit_backward,m.limit_backward=t,m.cursor=m.limit,m.ket=m.cursor,e=m.find_among_b(a,5))switch(m.bra=m.cursor,e){case 1:m.slice_del();break;case 2:m.slice_from("lös");break;case 3:m.slice_from("full")}m.limit_backward=r}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}}); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
Subproject commit 361f59c21a733a484f48e9bd60bce2d94dbf7b1b |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
Subproject commit a87dcd5f3d997596c87deec03d396f0911b4b03f |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
version: "3.3" |
||||
services: |
||||
|
||||
stormy_nginx_subs: |
||||
restart: always |
||||
image: nginx |
||||
command: /bin/bash -c "nginx -g 'daemon off;'" |
||||
volumes: |
||||
- "./d-nginx-subdomains/conf.d:/etc/nginx/conf.d" |
||||
- "/www/pages.charlesreid1.red/htdocs:/www/pages.charlesreid1.red/htdocs:ro" |
||||
- "/www/hooks.charlesreid1.red/htdocs:/www/hooks.charlesreid1.red/htdocs:ro" |
||||
- "/www/bots.charlesreid1.red/htdocs:/www/bots.charlesreid1.red/htdocs:ro" |
||||
logging: |
||||
driver: "json-file" |
||||
options: |
||||
max-size: "1m" |
||||
max-file: "10" |
||||
ports: |
||||
- "7777:7777" |
||||
- "7778:7778" |
||||
- "7779:7779" |
||||
|
||||
stormy_captain_hook: |
||||
restart: always |
||||
build: b-captain-hook |
||||
volumes: |
||||
- "/www/pages.charlesreid1.red:/www/pages.charlesreid1.red" |
||||
- "/www/hooks.charlesreid1.red:/www/hooks.charlesreid1.red" |
||||
- "/www/bots.charlesreid1.red:/www/bots.charlesreid1.red" |
||||
- "/tmp/triggers:/tmp/triggers" |
||||
- "./b-captain-hook/config.json:/app/config.json" |
||||
- "./b-captain-hook/hooks:/app/hooks" |
||||
logging: |
||||
driver: "json-file" |
||||
options: |
||||
max-size: "1m" |
||||
max-file: "10" |
||||
ports: |
||||
- "5000:5000" |
||||
depends_on: |
||||
- stormy_nginx_subs |
||||
|
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
version: "3.3" |
||||
services: |
||||
|
||||
stormy_nginx_subs: |
||||
restart: always |
||||
image: nginx |
||||
command: /bin/bash -c "nginx -g 'daemon off;'" |
||||
volumes: |
||||
- "./d-nginx-subdomains/conf.d:/etc/nginx/conf.d" |
||||
- "/www/pages.{{ server_name_default }}/htdocs:/www/pages.{{ server_name_default }}/htdocs:ro" |
||||
- "/www/hooks.{{ server_name_default }}/htdocs:/www/hooks.{{ server_name_default }}/htdocs:ro" |
||||
- "/www/bots.{{ server_name_default }}/htdocs:/www/bots.{{ server_name_default }}/htdocs:ro" |
||||
logging: |
||||
driver: "json-file" |
||||
options: |
||||
max-size: "1m" |
||||
max-file: "10" |
||||
ports: |
||||
- "7777:7777" |
||||
- "7778:7778" |
||||
- "7779:7779" |
||||
|
||||
stormy_captain_hook: |
||||
restart: always |
||||
build: b-captain-hook |
||||
volumes: |
||||
- "/www/pages.{{ server_name_default }}:/www/pages.{{ server_name_default }}" |
||||
- "/www/hooks.{{ server_name_default }}:/www/hooks.{{ server_name_default }}" |
||||
- "/www/bots.{{ server_name_default }}:/www/bots.{{ server_name_default }}" |
||||
- "/tmp/triggers:/tmp/triggers" |
||||
- "./b-captain-hook/config.json:/app/config.json" |
||||
- "./b-captain-hook/hooks:/app/hooks" |
||||
logging: |
||||
driver: "json-file" |
||||
options: |
||||
max-size: "1m" |
||||
max-file: "10" |
||||
ports: |
||||
- "5000:5000" |
||||
depends_on: |
||||
- stormy_nginx_subs |
||||
|
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
## Adding New Hooks |
||||
|
||||
To add a hook to Captain Hook: |
||||
|
||||
1. Create an executable script in [bots/b-captain-hook](https://git.charlesreid1.com/bots/b-captain-hook) |
||||
on git.charlesreid1.com with the name of the action, the name of the repo (not the owner), |
||||
and the name of the branch in the filename. For example, `push-my-dotfiles-master` would be |
||||
matched every time I `push` changes to the `master` branch of any repository named `my-dotfiles`. |
||||
|
||||
2. Add, commit, and push your hook to the master branch of Captain Hook |
||||
|
||||
3. Wait about 15 seconds for the canary script to run (it has to update |
||||
the Captain Hook git repo running on the remote server to the latest version |
||||
and restart the webhooks-subdomains docker pod.) |
||||
|
||||
4. Open the `my-dotfiles` repository on git.charlesreid1.com, go to the |
||||
Settings > Webhooks page, and add a Gitea webhook. |
||||
|
||||
5. Enter info: |
||||
|
||||
a. Payload URL is the Captain Hook server, which is `https://hooks.charlesreid1.com/webhook`. |
||||
b. Content type is `application/json` |
||||
c. Secret is (that's my little secret) |
||||
d. Pick what events you would like to trigger webhooks, usually "just the push event" |
||||
|
||||
6. Save the webhook, then click on the webhook again to open it back up. |
||||
Scroll down to the bottom right and click "Test Delivery". |
||||
|
||||
You should see a green success sign. |
||||
|
||||
|
||||
## Debugging Failed Hooks |
||||
|
||||
If you see a red warning sign: |
||||
|
||||
* Ensure the webhooks docker pod is actually running okay (`docker ps` on the host machine) |
||||
* Ensure port 5000 is open in the Captain Hook container, and on the host machine |
||||
* Ensure you can see port 5000 of the `pod-webhooks` host machine from the `pod-charlesreid1` host machine |
||||
* Ensure there is actually a hook in the `hooks/` directory of the Captain Hook repo |
||||
|
||||
Captain Hook repo: <https://git.charlesreid1.com/bots/b-captain-hook> |
||||
|
||||
Captain Hook repo (Github mirror): <https://github.com/charlesreid1-docker/b-captain-hook> |
||||
|
@ -0,0 +1,148 @@
@@ -0,0 +1,148 @@
|
||||
# Captain Hook's Canary |
||||
|
||||
First things first: Captain Hook is the webhook server that |
||||
is part of the webhooks docker pod. It receives webhooks |
||||
from Github and Gitea and uses them to trigger scrips. |
||||
Links to [documentation](https://pages.charlesreid1.com/b-captain-hook) |
||||
and [code](https://git.charlesreid1.com/bots/b-captain-hook) |
||||
for Captain Hook. |
||||
|
||||
Captain Hook's Canary is a mechanism by which the Captain Hook |
||||
webhooks server (running in a docker container) can trigger an action |
||||
on the host machine (running the pod). In this case the action is to |
||||
update Captain Hook and restart the docker pod anytime a webhook is |
||||
received indicating the Captain Hook repo has changed. |
||||
|
||||
This is done by bind-mounting a host directory at `/tmp/triggers/` |
||||
inside the Captain Hook docker container. When Captain Hook receives |
||||
a webhook from Github or Gitea that indicates the Captain Hook |
||||
repo (<https://git.charlesreid1.com/bots/b-captain-hook> or |
||||
<https://github.com/charlesreid1/captain-hook>), it creates a |
||||
trigger file. |
||||
|
||||
Meanwhile, on the host that is running the docker pod, a service |
||||
script is running continuously to check for that trigger file |
||||
every 10 seconds. If the trigger file is seen, it updates the |
||||
Captain Hook git repository on the host machine and then restarts |
||||
the docker pod. |
||||
|
||||
Sections below cover the following scripts, all run on the host: |
||||
|
||||
* The canary bash script |
||||
* The docker host pull script |
||||
* The canary statup service |
||||
|
||||
## The Canary Bash Script |
||||
|
||||
Note: this needs an associated systemd service. |
||||
See the services directory of the dotfiles repo. |
||||
|
||||
This is a canary script for connecting |
||||
the Captain Hook container to the host |
||||
machine, and triggering tasks on the |
||||
host machine with webhooks. |
||||
|
||||
The Captain Hook container mounts the |
||||
following host directory inside the |
||||
container (same location for host/container): |
||||
|
||||
``` |
||||
/tmp/triggers/ |
||||
``` |
||||
|
||||
When a webhook in Captain Hook wants to |
||||
trigger an event on the host (blackbeard), |
||||
it puts a file in `/tmp/triggers/`. |
||||
|
||||
Meanwhile, on the host, this script checks |
||||
every 10 seconds for trigger files. |
||||
|
||||
Each webhook can create its own trigger file, |
||||
and this script processes each trigger differently. |
||||
|
||||
```bash |
||||
#!/bin/bash |
||||
|
||||
TRIGGER="/tmp/triggers/push-b-captain-hook-master" |
||||
UPDATE_SCRIPT="${HOME}/pod-webhooks/scripts/captain_hook_pull_host.py" |
||||
|
||||
while true |
||||
do |
||||
# bootstrap-pull captain hook |
||||
if [ -f "$TRIGGER" ]; then |
||||
echo "CAPTAIN HOOK'S CANARY:" |
||||
echo "Running trigger to update Captain Hook on the host machine (user charles)" |
||||
sudo -H -u charles python $UPDATE_SCRIPT |
||||
echo "All done." |
||||
rm -f ${TRIGGER} |
||||
fi |
||||
|
||||
sleep 10; |
||||
done |
||||
``` |
||||
|
||||
|
||||
## The Pull Host Captain Hook Script |
||||
|
||||
Next we have a python script that actually updates the host's |
||||
version of Captain Hook: |
||||
|
||||
```python |
||||
#!/usr/bin/env python3 |
||||
import subprocess |
||||
import os |
||||
import time |
||||
|
||||
""" |
||||
Captain Hook: Pull Captain Hook on the Host |
||||
|
||||
This script is called by the host machine |
||||
(blackbeard) running the Captain Hook container. |
||||
|
||||
This is triggered by push actions to the |
||||
master branch of b-captain-hook. |
||||
|
||||
The action is to update (git pull) the copy |
||||
of Captain Hook running on the host, and |
||||
restart the container pod. |
||||
""" |
||||
|
||||
work_dir = os.path.join('/home','charles','pod-webhooks','b-captain-hook') |
||||
|
||||
# Step 1: |
||||
# Update Captain Hook |
||||
pull_cmd = ['git','pull','origin','master'] |
||||
subprocess.call(pull_cmd, cwd=work_dir) |
||||
|
||||
time.sleep(5) |
||||
|
||||
# Step 2: |
||||
# Restart Captain Hook pod |
||||
pod_restart = ['docker-compose','restart'] |
||||
subprocess.call(pod_restart, cwd=work_dir) |
||||
``` |
||||
|
||||
## The Canary Startup Script |
||||
|
||||
Here is the startup file that runs the Captain Hook's Canary bash script. |
||||
|
||||
The stop directive uses pgrep to find the process id and stops any PIDs returned. |
||||
|
||||
``` |
||||
[Unit] |
||||
Description=captain hook canary script |
||||
Requires=pod-webhooks.service |
||||
After=pod-webhooks.service |
||||
|
||||
[Service] |
||||
Restart=always |
||||
ExecStart=/home/charles/pod-webhooks/scripts/captain_hook_canary.sh |
||||
ExecStop=/usr/bin/pgrep -f captain_hook_canary | /usr/bin/xargs /bin/kill |
||||
|
||||
[Install] |
||||
WantedBy=default.target |
||||
``` |
||||
|
||||
See [Services](services.md) for more info on what to do with this file. |
||||
|
||||
|
@ -0,0 +1,176 @@
@@ -0,0 +1,176 @@
|
||||
# pod-webhooks |
||||
|
||||
This docker pod runs two services: |
||||
|
||||
* Captain Hook webhook server (python + flask) |
||||
* [b-captain-hook](https://git.charlesreid1.com/bots/b-captain-hook) |
||||
* Static content server for subdomain pages (nginx) |
||||
* [d-nginx-subdomains](https://git.charlesreid1.com/docker/d-nginx-subdomains) |
||||
|
||||
These two services are in this repo as submodules. |
||||
|
||||
## Links |
||||
|
||||
See documentation page here: <https://pages.charlesreid1.com/pod-webhooks> |
||||
|
||||
Source code on git.charlesreid1.com: <https://git.charlesreid1.com/docker/pod-webhooks> |
||||
|
||||
Source code on github.com: <https://github.com/charlesreid1-docker/pod-webhooks> |
||||
|
||||
|
||||
## Initial Setup of Pages Subdomain |
||||
|
||||
The pages.charlesreid1.com subdomain is served from content |
||||
in the directory `/www/pages.charlesreid1.com`. |
||||
|
||||
To set this up with pages and sites that should exist already, |
||||
use the set up script at `scripts/pages_init_setup.py` and |
||||
run it on the pages.charlesreid1.com server: |
||||
|
||||
``` |
||||
python scripts/pages_init_setup.py |
||||
``` |
||||
|
||||
This will create the `/www/pages.charlesreid1.com/` directory |
||||
structure and will clone several repositories to populate it |
||||
with content. |
||||
|
||||
|
||||
## Adding Hooks |
||||
|
||||
Since this is probably the only thing you'll care about once everything |
||||
is actually running... until it breaks. |
||||
|
||||
[How To Add A Hook](adding.md) |
||||
|
||||
|
||||
## How It Works |
||||
|
||||
See [Running.md](running.md) for info about running this docker pod. |
||||
|
||||
* Running the Docker Pod from Comand Line |
||||
* Workflow for Docker Pod Updates |
||||
|
||||
See [Services.md](services.md) for info about running startup services. |
||||
|
||||
* Running the Docker Pod as a Startup Service |
||||
* Running Captain Hook's Canary (Script) |
||||
|
||||
Enable/disable service (installs/uninstalls, but does not start): |
||||
|
||||
``` |
||||
sudo systemctl (enable|disable) pod-webhooks.service |
||||
sudo systemctl (enable|disable) captain-hook-canary.service |
||||
``` |
||||
|
||||
Start/stop: |
||||
|
||||
``` |
||||
sudo systemctl (start|stop) pod-webhooks.service |
||||
sudo systemctl (start|stop) captain-hook-canary.service |
||||
``` |
||||
|
||||
See [Captain Hook's Canary](canary.md) for details on the canary script that allows the |
||||
webhooks docker pod to trigger itself to be re-loaded when there are new hooks |
||||
added to captain hook. |
||||
|
||||
|
||||
## Volumes and Files |
||||
|
||||
### Subdomains |
||||
|
||||
The static files hosted on charlesreid1.com subdomains are contained in |
||||
subdirectories of `/www/*.charlesreid1.com/` and this is |
||||
mounted by the subdomains docker container that has rules |
||||
set up for which subdomains to serve. |
||||
|
||||
### Captain Hook |
||||
|
||||
Captain Hook mounts the `/www` folder, which is served by the subdomains |
||||
nginx server, as well as the hooks folder in the Captain Hook repository |
||||
(that's at `b-captain-hook/hooks`). |
||||
|
||||
When there is a change pushed to a particular branch on git.charlesreid1.com, |
||||
the git.charlesreid1.com server will check if there is a corresponding hook that's |
||||
been added to Captain Hook for that repo and branch. If so, git.charlesreid1.com |
||||
runs that script. For pages.charlesreid1.com, that's usually just a git pull |
||||
on the contents of `/www/pages.charlesreid1.com/my-page`. |
||||
|
||||
### Captain Hook's Canary |
||||
|
||||
Captain Hook presents a bit of a paradox: what happens when Captain Hook installs |
||||
a hook for itself, and detects that Captain Hook itself has changed? |
||||
|
||||
In this case, the webhooks docker pod needs to be able to tell the host machine |
||||
to restart the webhooks docker pod. |
||||
|
||||
This is done by Captain Hook's Canary. This is a service script that checks every |
||||
10 seconds for a trigger file in a directory mounted between the host and container. |
||||
If the trigger file is present, the host will update its copy of Captain Hook, |
||||
then restart the webhooks-subdomains docker pod. |
||||
|
||||
As per the [dotfiles/debian](https://git.charlesreid1.com/dotfiles/debian) repo, |
||||
the `captain_hook_canary.sh` canary will restart the webhooks docker pod if it |
||||
detects the presence following file: |
||||
|
||||
``` |
||||
/tmp/triggers/push-b-captain-hook-master |
||||
``` |
||||
|
||||
(The canary script will remove this file once it has restarted the webhooks docker pod.) |
||||
|
||||
Now, a hook can be added to Captain Hook that will be run when there is a push event |
||||
on the master branch of [bots/b-captain-hook](https://git.charlesreid1.com/bots/b-captain-hook). |
||||
By creating a hook named `push-b-captain-hook-master` in the |
||||
`hooks/` directory of Captain Hook, and having it simply run |
||||
`touch /tmp/triggers/push-b-captain-hook-master`, |
||||
this webhook can trigger the Captain Hook's Canary service script, |
||||
which triggers a restart of the webhooks docker pod. |
||||
|
||||
Code: <https://git.charlesreid1.com/bots/b-captain-hook/src/branch/master/hooks/push-b-captain-hook-master> |
||||
|
||||
|
||||
## Network |
||||
|
||||
The `d-subodomains-nginx` container opens different ports for different |
||||
subdomains, and reverse-proxies requests from charlesreid1.com. |
||||
The port numbering starts at 7777 for pages.charlesreid1.com |
||||
and goes up from there, one port per subdomain. |
||||
|
||||
Also see [pod-charlesreid1](https://git.charlesreid1.com/docker/pod-charlesreid1) |
||||
on git.charlesreid1.com for the nginx reverse proxy configuration. |
||||
|
||||
Captain Hook runs a Flask server on port 5000 and listens for triggers |
||||
from git.charlesreid1.com (gitea) web hooks. These web hooks must have |
||||
the correct secret or the trigger will be ignored. |
||||
|
||||
|
||||
## Servers |
||||
|
||||
[pod-webhooks](https://pages.charlesreid1.com/pod-webhooks/) |
||||
runs on a virtual server somewhere. |
||||
|
||||
This pod's nginx service provides a backend that is |
||||
reverse-proxied by the machine running |
||||
[pod-charlesreid1](https://pages.charlesreid1.com/pod-charlesreid1) |
||||
(and the whole <https://charlesreid1.com> frontend). |
||||
It opens ports 7777+ and up (one per subdomain). |
||||
|
||||
The [pod-charlesreid1](https://pages.charlesreid1.com/pod-charlesreid1) |
||||
docker pod (actually the |
||||
[d-nginx-charlesreid1](https://pages.charlesreid1.com/d-nginx-charlesreid1/) |
||||
submodule in that pod) contains the nginx |
||||
config files that control the reverse proxy |
||||
behavior of <https://charlesreid1.com>. |
||||
|
||||
Like the nginx service in this webhooks pod, the Captain Hook |
||||
webhook service is also reverse-proxied by the main nginx frontend |
||||
running <https://charlesreid1.com> with the |
||||
[pod-charlesreid1](https://pages.charlesreid1.com/pod-charlesreid1) |
||||
docker pod. If a URL request for <https://hooks.charlesreid1.com> |
||||
is received by the <https://charlesreid1.com> server, |
||||
it is forwarded to the machine running the [pod-webhooks](https://git.charlesreid1.com/pod-webhooks) |
||||
docker pod, which decides whether it is a POST request |
||||
(that should be sent to this pod's Captain Hook) or a GET request |
||||
(that should be sent to this pod's nginx). |
||||
|
@ -0,0 +1,64 @@
@@ -0,0 +1,64 @@
|
||||
## The Docker Compose File |
||||
|
||||
The `docker-compose.yml` file contains everything needed to |
||||
run the webhooks docker pod: a Captain Hook webhook server, and |
||||
an nginx server to serve up static pages for each subdomain. |
||||
|
||||
Why use docker-compose instead of docker? |
||||
docker-compose is the preferred way to run multiple containers. |
||||
|
||||
## Running Webhooks Docker Pod from Command Line |
||||
|
||||
Run the pod in the foreground or background by running these |
||||
commands from the directory containing `docker-compose.yml`: |
||||
|
||||
``` |
||||
docker-compose up # interactive |
||||
docker-compose up -d # detached |
||||
``` |
||||
|
||||
If you want to rebuild all the containers before bringing |
||||
the pod up, add the `--build` flag: |
||||
|
||||
``` |
||||
docker-compose up --build |
||||
``` |
||||
|
||||
If you just want to rebuild the containers without bringing |
||||
them up, |
||||
|
||||
``` |
||||
docker-compose build |
||||
``` |
||||
|
||||
To rebuild absolutely everything from scratch, |
||||
|
||||
``` |
||||
docker-compose build --no-cache |
||||
``` |
||||
|
||||
***WARNING:*** this will re-download all aptitude packages, |
||||
which can be extremely slow. Use with caution. |
||||
|
||||
You can restart all containers in a pod using the restart command: |
||||
|
||||
``` |
||||
docker-compose restart |
||||
``` |
||||
|
||||
***WARNING:*** this will ***NOT*** pick up changes to |
||||
Dockerfiles or to files that are mounted into the container. |
||||
This simply restarts the container using the same image |
||||
(in memory) that was previously running, ***without*** |
||||
getting an up-to-date container image. |
||||
|
||||
## Workflow for Docker Pod Updates |
||||
|
||||
To minimize downtime, use the following workflow: |
||||
|
||||
* Run `docker-compose build` to rebuild the images, leaving the pod running (they are not affected) |
||||
* Run `docker-compose down` to bring the pod down |
||||
* Run `docker-compose up` to bring the pod up |
||||
|
||||
(Add the `-d` flag to start the docker pod in the background.) |
||||
|
@ -0,0 +1,93 @@
@@ -0,0 +1,93 @@
|
||||
## Running Hooks-Subdomains Docker Pod as Startup Service |
||||
|
||||
The webhooks-subdomains docker pod requires two startup |
||||
services: |
||||
|
||||
* Docker pod service - this startup service keeps the pod running, |
||||
and will restart it if it crashes |
||||
|
||||
* Captain Hook's canary - this watches a folder that is shared between |
||||
the docker pod host and the Captain Hook container, which allows the |
||||
pod to send triggers to the host. |
||||
|
||||
Also see the `scripts/` folder of this repo, |
||||
[pod-webhooks](https://git.charlesreid1.com/docker/pod-webhooks) |
||||
([Github mirror](https://github.com/charlesreid1-docker/pod-webhooks)). |
||||
|
||||
|
||||
### Docker Pod Startup Service |
||||
|
||||
This service keeps the webhooks docker pod service running |
||||
continuously. If the pod stops, this service will restart it. |
||||
|
||||
(This service should not be running if you are troubleshooting |
||||
the docker pod, otherwise every time you try and stop the pod |
||||
it will respawn.) |
||||
|
||||
**`pod-webhooks.service:`** |
||||
|
||||
``` |
||||
[Unit] |
||||
Description=webhooks and subdomains docker pod |
||||
Requires=docker.service |
||||
After=docker.service |
||||
|
||||
[Service] |
||||
Restart=always |
||||
ExecStart=/usr/local/bin/docker-compose -f /home/charles/codes/docker/pod-webhooks/docker-compose.yml up |
||||
ExecStop=/usr/local/bin/docker-compose -f /home/charles/codes/docker/pod-webhooks/docker-compose.yml down |
||||
|
||||
[Install] |
||||
WantedBy=default.target |
||||
``` |
||||
|
||||
|
||||
### Captain Hook's Canary Startup Service |
||||
|
||||
This service just watches a folder for a particular |
||||
watchfile, and runs a script if it sees the watchfile |
||||
appear. |
||||
|
||||
**`captain-hook-canary.service:`** |
||||
|
||||
``` |
||||
[Unit] |
||||
Description=captain hook canary script |
||||
Requires=pod-webhooks.service |
||||
After=pod-webhooks.service |
||||
|
||||
[Service] |
||||
Restart=always |
||||
ExecStart=/home/charles/pod-webhooks/scripts/captain_hook_canary.sh |
||||
ExecStop=/usr/bin/pgrep -f captain_hook_canary | /usr/bin/xargs /bin/kill |
||||
|
||||
[Install] |
||||
WantedBy=default.target |
||||
``` |
||||
|
||||
### Installing Services |
||||
|
||||
Install the services by copying the `*.service` files |
||||
to `/etc/systemd/system/dockerpod-webhooks.servce` |
||||
and `/etc/systemd/system/captain-hook-canary.servce`, |
||||
and activate the startup services: |
||||
|
||||
``` |
||||
sudo systemctl enable pod-webhooks.service |
||||
|
||||
sudo systemctl enable captain-hook-canary.service |
||||
``` |
||||
|
||||
Now you can start/stop the services with: |
||||
|
||||
``` |
||||
sudo systemctl (start|stop) pod-webhooks.service |
||||
|
||||
sudo systemctl (start|stop) captain-hook-canary.service |
||||
``` |
||||
|
||||
As mentioned above, these services should be stopped before |
||||
doing a `docker-compose stop` or a `docker-compose up --build` |
||||
to keep the pod from respawning in the middle of the task. |
||||
|
||||
|
@ -1,696 +0,0 @@
@@ -1,696 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html> |
||||
<html lang="en" class="no-js"> |
||||
<head> |
||||
|
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width,initial-scale=1"> |
||||
<meta http-equiv="x-ua-compatible" content="ie=edge"> |
||||
|
||||
|
||||
<link rel="canonical" href="https://pages.charlesreid1.com/pod-webhooks/"> |
||||
|
||||
|
||||
|
||||
<meta name="lang:clipboard.copy" content="Copy to clipboard"> |
||||
|
||||
<meta name="lang:clipboard.copied" content="Copied to clipboard"> |
||||
|
||||
<meta name="lang:search.language" content="en"> |
||||
|
||||
<meta name="lang:search.pipeline.stopwords" content="True"> |
||||
|
||||
<meta name="lang:search.pipeline.trimmer" content="True"> |
||||
|
||||
<meta name="lang:search.result.none" content="No matching documents"> |
||||
|
||||
<meta name="lang:search.result.one" content="1 matching document"> |
||||
|
||||
<meta name="lang:search.result.other" content="# matching documents"> |
||||
|
||||
<meta name="lang:search.tokenizer" content="[\s\-]+"> |
||||
|
||||
<link rel="shortcut icon" href="."> |
||||
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-3.0.3"> |
||||
|
||||
|
||||
|
||||
<title>pod-webhooks</title> |
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="assets/stylesheets/application.451f80e5.css"> |
||||
|
||||
<link rel="stylesheet" href="assets/stylesheets/application-palette.22915126.css"> |
||||
|
||||
|
||||
|
||||
|
||||
<meta name="theme-color" content="#2196f3"> |
||||
|
||||
|
||||
|
||||
<script src="assets/javascripts/modernizr.1aa3b519.js"></script> |
||||
|
||||
|
||||
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin> |
||||
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono"> |
||||
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style> |
||||
|
||||
|
||||
<link rel="stylesheet" href="assets/fonts/material-icons.css"> |
||||
|
||||
<link rel="stylesheet" href="css/custom.css"> |
||||
|
||||
|
||||
</head> |
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-primary="blue" data-md-color-accent="blue"> |
||||
|
||||
<svg class="md-svg"> |
||||
<defs> |
||||
|
||||
|
||||
</defs> |
||||
</svg> |
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off"> |
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> |
||||
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label> |
||||
|
||||
<a href="#pod-webhooks" tabindex="1" class="md-skip"> |
||||
Skip to content |
||||
</a> |
||||
|
||||
|
||||
<header class="md-header" data-md-component="header"> |
||||
<nav class="md-header-nav md-grid"> |
||||
<div class="md-flex"> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<a href="https://pages.charlesreid1.com/pod-webhooks" title="pod-webhooks" class="md-header-nav__button md-logo"> |
||||
|
||||
<i class="md-icon">dns</i> |
||||
|
||||
</a> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--stretch"> |
||||
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title"> |
||||
|
||||
|
||||
<span class="md-header-nav__topic"> |
||||
pod-webhooks |
||||
</span> |
||||
<span class="md-header-nav__topic"> |
||||
Home |
||||
</span> |
||||
|
||||
|
||||
</div> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
|
||||
|
||||
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label> |
||||
|
||||
<div class="md-search" data-md-component="search" role="dialog"> |
||||
<label class="md-search__overlay" for="__search"></label> |
||||
<div class="md-search__inner" role="search"> |
||||
<form class="md-search__form" name="search"> |
||||
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active"> |
||||
<label class="md-icon md-search__icon" for="__search"></label> |
||||
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1"> |
||||
 |
||||
</button> |
||||
</form> |
||||
<div class="md-search__output"> |
||||
<div class="md-search__scrollwrap" data-md-scrollfix> |
||||
<div class="md-search-result" data-md-component="result"> |
||||
<div class="md-search-result__meta"> |
||||
Type to start searching |
||||
</div> |
||||
<ol class="md-search-result__list"></ol> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
</div> |
||||
|
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<div class="md-header-nav__source"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://git.charlesreid1.com/docker/pod-webhooks" title="Go to repository" class="md-source" data-md-source=""> |
||||
|
||||
<div class="md-source__repository"> |
||||
pod-webhooks |
||||
</div> |
||||
</a> |
||||
|
||||
</div> |
||||
</div> |
||||
|
||||
</div> |
||||
</nav> |
||||
</header> |
||||
|
||||
<div class="md-container"> |
||||
|
||||
|
||||
|
||||
<main class="md-main"> |
||||
<div class="md-main__inner md-grid" data-md-component="container"> |
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation"> |
||||
<div class="md-sidebar__scrollwrap"> |
||||
<div class="md-sidebar__inner"> |
||||
<nav class="md-nav md-nav--primary" data-md-level="0"> |
||||
<label class="md-nav__title md-nav__title--site" for="__drawer"> |
||||
<a href="https://pages.charlesreid1.com/pod-webhooks" title="pod-webhooks" class="md-nav__button md-logo"> |
||||
|
||||
<i class="md-icon">dns</i> |
||||
|
||||
</a> |
||||
pod-webhooks |
||||
</label> |
||||
|
||||
<div class="md-nav__source"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://git.charlesreid1.com/docker/pod-webhooks" title="Go to repository" class="md-source" data-md-source=""> |
||||
|
||||
<div class="md-source__repository"> |
||||
pod-webhooks |
||||
</div> |
||||
</a> |
||||
|
||||
</div> |
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--active"> |
||||
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc"> |
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__link md-nav__link--active" for="__toc"> |
||||
Home |
||||
</label> |
||||
|
||||
<a href="." title="Home" class="md-nav__link md-nav__link--active"> |
||||
Home |
||||
</a> |
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#links" title="Links" class="md-nav__link"> |
||||
Links |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#initial-setup-of-pages-subdomain" title="Initial Setup of Pages Subdomain" class="md-nav__link"> |
||||
Initial Setup of Pages Subdomain |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#adding-hooks" title="Adding Hooks" class="md-nav__link"> |
||||
Adding Hooks |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#how-it-works" title="How It Works" class="md-nav__link"> |
||||
How It Works |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#volumes-and-files" title="Volumes and Files" class="md-nav__link"> |
||||
Volumes and Files |
||||
</a> |
||||
|
||||
<nav class="md-nav"> |
||||
<ul class="md-nav__list"> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#subdomains" title="Subdomains" class="md-nav__link"> |
||||
Subdomains |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#captain-hook" title="Captain Hook" class="md-nav__link"> |
||||
Captain Hook |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#captain-hooks-canary" title="Captain Hook's Canary" class="md-nav__link"> |
||||
Captain Hook's Canary |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
</ul> |
||||
</nav> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#network" title="Network" class="md-nav__link"> |
||||
Network |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#servers" title="Servers" class="md-nav__link"> |
||||
Servers |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul> |
||||
|
||||
</nav> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="adding/" title="Adding Webhooks" class="md-nav__link"> |
||||
Adding Webhooks |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="running/" title="Running Captain Hook" class="md-nav__link"> |
||||
Running Captain Hook |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="services/" title="Captain Hook Startup Services" class="md-nav__link"> |
||||
Captain Hook Startup Services |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="canary/" title="Captain Hook's Canary" class="md-nav__link"> |
||||
Captain Hook's Canary |
||||
</a> |
||||
</li> |
||||
|
||||
|
||||
</ul> |
||||
</nav> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc"> |
||||
<div class="md-sidebar__scrollwrap"> |
||||
<div class="md-sidebar__inner"> |
||||
|
||||
<nav class="md-nav md-nav--secondary"> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||
<ul class="md-nav__list" data-md-scrollfix> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#links" title="Links" class="md-nav__link"> |
||||
Links |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#initial-setup-of-pages-subdomain" title="Initial Setup of Pages Subdomain" class="md-nav__link"> |
||||
Initial Setup of Pages Subdomain |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#adding-hooks" title="Adding Hooks" class="md-nav__link"> |
||||
Adding Hooks |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#how-it-works" title="How It Works" class="md-nav__link"> |
||||
How It Works |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#volumes-and-files" title="Volumes and Files" class="md-nav__link"> |
||||
Volumes and Files |
||||
</a> |
||||
|
||||
<nav class="md-nav"> |
||||
<ul class="md-nav__list"> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#subdomains" title="Subdomains" class="md-nav__link"> |
||||
Subdomains |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#captain-hook" title="Captain Hook" class="md-nav__link"> |
||||
Captain Hook |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#captain-hooks-canary" title="Captain Hook's Canary" class="md-nav__link"> |
||||
Captain Hook's Canary |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
</ul> |
||||
</nav> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#network" title="Network" class="md-nav__link"> |
||||
Network |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
<li class="md-nav__item"> |
||||
<a href="#servers" title="Servers" class="md-nav__link"> |
||||
Servers |
||||
</a> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul> |
||||
|
||||
</nav> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<div class="md-content"> |
||||
<article class="md-content__inner md-typeset"> |
||||
|
||||
|
||||
|
||||
<h1 id="pod-webhooks">pod-webhooks<a class="headerlink" href="#pod-webhooks" title="Permanent link">¶</a></h1> |
||||
<p>This docker pod runs two services:</p> |
||||
<ul> |
||||
<li>Captain Hook webhook server (python + flask)<ul> |
||||
<li><a href="https://git.charlesreid1.com/bots/b-captain-hook">b-captain-hook</a></li> |
||||
</ul> |
||||
</li> |
||||
<li>Static content server for subdomain pages (nginx)<ul> |
||||
<li><a href="https://git.charlesreid1.com/docker/d-nginx-subdomains">d-nginx-subdomains</a></li> |
||||
</ul> |
||||
</li> |
||||
</ul> |
||||
<p>These two services are in this repo as submodules.</p> |
||||
<h2 id="links">Links<a class="headerlink" href="#links" title="Permanent link">¶</a></h2> |
||||
<p>See documentation page here: <a href="https://pages.charlesreid1.com/pod-webhooks">https://pages.charlesreid1.com/pod-webhooks</a></p> |
||||
<p>Source code on git.charlesreid1.com: <a href="https://git.charlesreid1.com/docker/pod-webhooks">https://git.charlesreid1.com/docker/pod-webhooks</a></p> |
||||
<p>Source code on github.com: <a href="https://github.com/charlesreid1-docker/pod-webhooks">https://github.com/charlesreid1-docker/pod-webhooks</a></p> |
||||
<h2 id="initial-setup-of-pages-subdomain">Initial Setup of Pages Subdomain<a class="headerlink" href="#initial-setup-of-pages-subdomain" title="Permanent link">¶</a></h2> |
||||
<p>The pages.charlesreid1.com subdomain is served from content |
||||
in the directory <code>/www/pages.charlesreid1.com</code>.</p> |
||||
<p>To set this up with pages and sites that should exist already, |
||||
use the set up script at <code>scripts/pages_init_setup.py</code> and |
||||
run it on the pages.charlesreid1.com server:</p> |
||||
<div class="codehilite"><pre><span></span>python scripts/pages_init_setup.py |
||||
</pre></div> |
||||
|
||||
|
||||
<p>This will create the <code>/www/pages.charlesreid1.com/</code> directory |
||||
structure and will clone several repositories to populate it |
||||
with content.</p> |
||||
<h2 id="adding-hooks">Adding Hooks<a class="headerlink" href="#adding-hooks" title="Permanent link">¶</a></h2> |
||||
<p>Since this is probably the only thing you'll care about once everything |
||||
is actually running... until it breaks.</p> |
||||
<p><a href="adding/">How To Add A Hook</a></p> |
||||
<h2 id="how-it-works">How It Works<a class="headerlink" href="#how-it-works" title="Permanent link">¶</a></h2> |
||||
<p>See <a href="running/">Running.md</a> for info about running this docker pod.</p> |
||||
<ul> |
||||
<li>Running the Docker Pod from Comand Line</li> |
||||
<li>Workflow for Docker Pod Updates</li> |
||||
</ul> |
||||
<p>See <a href="services/">Services.md</a> for info about running startup services.</p> |
||||
<ul> |
||||
<li>Running the Docker Pod as a Startup Service</li> |
||||
<li>Running Captain Hook's Canary (Script)</li> |
||||
</ul> |
||||
<p>Enable/disable service (installs/uninstalls, but does not start):</p> |
||||
<div class="codehilite"><pre><span></span>sudo systemctl (enable|disable) pod-webhooks.service |
||||
sudo systemctl (enable|disable) captain-hook-canary.service |
||||
</pre></div> |
||||
|
||||
|
||||
<p>Start/stop:</p> |
||||
<div class="codehilite"><pre><span></span>sudo systemctl (start|stop) pod-webhooks.service |
||||
sudo systemctl (start|stop) captain-hook-canary.service |
||||
</pre></div> |
||||
|
||||
|
||||
<p>See <a href="canary/">Captain Hook's Canary</a> for details on the canary script that allows the |
||||
webhooks docker pod to trigger itself to be re-loaded when there are new hooks |
||||
added to captain hook.</p> |
||||
<h2 id="volumes-and-files">Volumes and Files<a class="headerlink" href="#volumes-and-files" title="Permanent link">¶</a></h2> |
||||
<h3 id="subdomains">Subdomains<a class="headerlink" href="#subdomains" title="Permanent link">¶</a></h3> |
||||
<p>The static files hosted on charlesreid1.com subdomains are contained in |
||||
subdirectories of <code>/www/*.charlesreid1.com/</code> and this is |
||||
mounted by the subdomains docker container that has rules |
||||
set up for which subdomains to serve.</p> |
||||
<h3 id="captain-hook">Captain Hook<a class="headerlink" href="#captain-hook" title="Permanent link">¶</a></h3> |
||||
<p>Captain Hook mounts the <code>/www</code> folder, which is served by the subdomains |
||||
nginx server, as well as the hooks folder in the Captain Hook repository |
||||
(that's at <code>b-captain-hook/hooks</code>).</p> |
||||
<p>When there is a change pushed to a particular branch on git.charlesreid1.com, |
||||
the git.charlesreid1.com server will check if there is a corresponding hook that's |
||||
been added to Captain Hook for that repo and branch. If so, git.charlesreid1.com |
||||
runs that script. For pages.charlesreid1.com, that's usually just a git pull |
||||
on the contents of <code>/www/pages.charlesreid1.com/my-page</code>.</p> |
||||
<h3 id="captain-hooks-canary">Captain Hook's Canary<a class="headerlink" href="#captain-hooks-canary" title="Permanent link">¶</a></h3> |
||||
<p>Captain Hook presents a bit of a paradox: what happens when Captain Hook installs |
||||
a hook for itself, and detects that Captain Hook itself has changed?</p> |
||||
<p>In this case, the webhooks docker pod needs to be able to tell the host machine |
||||
to restart the webhooks docker pod.</p> |
||||
<p>This is done by Captain Hook's Canary. This is a service script that checks every |
||||
10 seconds for a trigger file in a directory mounted between the host and container. |
||||
If the trigger file is present, the host will update its copy of Captain Hook, |
||||
then restart the webhooks-subdomains docker pod.</p> |
||||
<p>As per the <a href="https://git.charlesreid1.com/dotfiles/debian">dotfiles/debian</a> repo, |
||||
the <code>captain_hook_canary.sh</code> canary will restart the webhooks docker pod if it |
||||
detects the presence following file:</p> |
||||
<div class="codehilite"><pre><span></span>/tmp/triggers/push-b-captain-hook-master |
||||
</pre></div> |
||||
|
||||
|
||||
<p>(The canary script will remove this file once it has restarted the webhooks docker pod.)</p> |
||||
<p>Now, a hook can be added to Captain Hook that will be run when there is a push event |
||||
on the master branch of <a href="https://git.charlesreid1.com/bots/b-captain-hook">bots/b-captain-hook</a>. |
||||
By creating a hook named <code>push-b-captain-hook-master</code> in the |
||||
<code>hooks/</code> directory of Captain Hook, and having it simply run |
||||
<code>touch /tmp/triggers/push-b-captain-hook-master</code>, |
||||
this webhook can trigger the Captain Hook's Canary service script, |
||||
which triggers a restart of the webhooks docker pod.</p> |
||||
<p>Code: <a href="https://git.charlesreid1.com/bots/b-captain-hook/src/branch/master/hooks/push-b-captain-hook-master">https://git.charlesreid1.com/bots/b-captain-hook/src/branch/master/hooks/push-b-captain-hook-master</a></p> |
||||
<h2 id="network">Network<a class="headerlink" href="#network" title="Permanent link">¶</a></h2> |
||||
<p>The <code>d-subodomains-nginx</code> container opens different ports for different |
||||
subdomains, and reverse-proxies requests from charlesreid1.com. |
||||
The port numbering starts at 7777 for pages.charlesreid1.com |
||||
and goes up from there, one port per subdomain.</p> |
||||
<p>Also see <a href="https://git.charlesreid1.com/docker/pod-charlesreid1">pod-charlesreid1</a> |
||||
on git.charlesreid1.com for the nginx reverse proxy configuration.</p> |
||||
<p>Captain Hook runs a Flask server on port 5000 and listens for triggers |
||||
from git.charlesreid1.com (gitea) web hooks. These web hooks must have |
||||
the correct secret or the trigger will be ignored.</p> |
||||
<h2 id="servers">Servers<a class="headerlink" href="#servers" title="Permanent link">¶</a></h2> |
||||
<p><a href="https://pages.charlesreid1.com/pod-webhooks/">pod-webhooks</a> |
||||
runs on a virtual server somewhere.</p> |
||||
<p>This pod's nginx service provides a backend that is |
||||
reverse-proxied by the machine running |
||||
<a href="https://pages.charlesreid1.com/pod-charlesreid1">pod-charlesreid1</a> |
||||
(and the whole <a href="https://charlesreid1.com">https://charlesreid1.com</a> frontend). |
||||
It opens ports 7777+ and up (one per subdomain).</p> |
||||
<p>The <a href="https://pages.charlesreid1.com/pod-charlesreid1">pod-charlesreid1</a> |
||||
docker pod (actually the |
||||
<a href="https://pages.charlesreid1.com/d-nginx-charlesreid1/">d-nginx-charlesreid1</a> |
||||
submodule in that pod) contains the nginx |
||||
config files that control the reverse proxy |
||||
behavior of <a href="https://charlesreid1.com">https://charlesreid1.com</a>.</p> |
||||
<p>Like the nginx service in this webhooks pod, the Captain Hook |
||||
webhook service is also reverse-proxied by the main nginx frontend |
||||
running <a href="https://charlesreid1.com">https://charlesreid1.com</a> with the |
||||
<a href="https://pages.charlesreid1.com/pod-charlesreid1">pod-charlesreid1</a> |
||||
docker pod. If a URL request for <a href="https://hooks.charlesreid1.com">https://hooks.charlesreid1.com</a> |
||||
is received by the <a href="https://charlesreid1.com">https://charlesreid1.com</a> server, |
||||
it is forwarded to the machine running the <a href="https://git.charlesreid1.com/pod-webhooks">pod-webhooks</a> |
||||
docker pod, which decides whether it is a POST request |
||||
(that should be sent to this pod's Captain Hook) or a GET request |
||||
(that should be sent to this pod's nginx).</p> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article> |
||||
</div> |
||||
</div> |
||||
</main> |
||||
|
||||
|
||||
<footer class="md-footer"> |
||||
|
||||
<div class="md-footer-nav"> |
||||
<nav class="md-footer-nav__inner md-grid"> |
||||
|
||||
|
||||
<a href="adding/" title="Adding Webhooks" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next"> |
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"> |
||||
<span class="md-flex__ellipsis"> |
||||
<span class="md-footer-nav__direction"> |
||||
Next |
||||
</span> |
||||
Adding Webhooks |
||||
</span> |
||||
</div> |
||||
<div class="md-flex__cell md-flex__cell--shrink"> |
||||
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i> |
||||
</div> |
||||
</a> |
||||
|
||||
</nav> |
||||
</div> |
||||
|
||||
<div class="md-footer-meta md-typeset"> |
||||
<div class="md-footer-meta__inner md-grid"> |
||||
<div class="md-footer-copyright"> |
||||
|
||||
<div class="md-footer-copyright__highlight"> |
||||
Copyright © 2018 <a href="https://charlesreid1.com">Charles Reid</a>, released under the <a href="https://opensource.org/licenses/MIT">MIT license</a> |
||||
</div> |
||||
|
||||
powered by |
||||
<a href="https://www.mkdocs.org">MkDocs</a> |
||||
and |
||||
<a href="https://squidfunk.github.io/mkdocs-material/"> |
||||
Material for MkDocs</a> |
||||
</div> |
||||
|
||||
|
||||
|
||||
</div> |
||||
</div> |
||||
</footer> |
||||
|
||||
</div> |
||||
|
||||
<script src="assets/javascripts/application.e72fd936.js"></script> |
||||
|
||||
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script> |
||||
|
||||
<script src="search/main.js"></script> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</body> |
||||
</html> |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
Subproject commit b0c6890853aa9138baf5f9749862b927518ab656 |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
site_name: pod-webhooks |
||||
site_url: https://pages.charlesreid1.com/pod-webhooks |
||||
repo_name: pod-webhooks |
||||
repo_url: https://git.charlesreid1.com/docker/pod-webhooks |
||||
edit_uri: "" |
||||
copyright: 'Copyright © 2018 <a href="https://charlesreid1.com">Charles Reid</a>, released under the <a href="https://opensource.org/licenses/MIT">MIT license</a>' |
||||
|
||||
docs_dir: docs |
||||
site_dir: site |
||||
extra_css: |
||||
- css/custom.css |
||||
theme: |
||||
name: null |
||||
custom_dir: 'mkdocs-material/material' |
||||
palette: |
||||
primary: 'blue' |
||||
accent: 'blue' |
||||
logo: |
||||
icon: 'dns' |
||||
font: |
||||
text: 'Roboto' |
||||
code: 'Roboto Mono' |
||||
nav: |
||||
- "Home": "index.md" |
||||
- "Adding Webhooks": "adding.md" |
||||
- "Running Captain Hook": "running.md" |
||||
- "Captain Hook Startup Services": "services.md" |
||||
- "Captain Hook's Canary": "canary.md" |
||||
|
||||
# Extensions |
||||
markdown_extensions: |
||||
- admonition |
||||
- codehilite: |
||||
guess_lang: false |
||||
- toc: |
||||
permalink: true |
||||
|
||||
strict: true |
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
# pod-webhooks scripts |
||||
|
||||
Copy this `pod-webhooks.service` service script to |
||||
`/etc/systemd/system/pod-webhooks.service`: |
||||
|
||||
``` |
||||
sudo cp pod-webhooks.service /etc/systemd/system/pod-webhooks.service |
||||
``` |
||||
|
||||
Enable/disable the service: |
||||
|
||||
``` |
||||
sudo systemctl enable pod-webhooks |
||||
sudo systemctl disable pod-webhooks |
||||
``` |
||||
|
||||
Start/restart/stop the service: |
||||
|
||||
``` |
||||
sudo systemctl start pod-webhooks |
||||
sudo systemctl restart pod-webhooks |
||||
sudo systemctl stop pod-webhooks |
||||
``` |
||||
|
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
import os, re, sys |
||||
import glob |
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape |
||||
|
||||
""" |
||||
Apply Default Values to |
||||
Captain Hook Jinja Templates |
||||
|
||||
|
||||
This script applies default values to |
||||
templates in this folder. |
||||
|
||||
The templates are used by Ansible, |
||||
but this script uses the same template |
||||
engine as Ansible to apply template |
||||
variable values to the template files |
||||
and make real files. |
||||
|
||||
variables are: |
||||
- `webhooks_install_dir` - location of pod-webhooks repo |
||||
|
||||
- `username` - user/group name to change ownership to |
||||
- `server_name_default` - name of server |
||||
(e.g., charlesreid1.com or charlesreid1.red) |
||||
""" |
||||
|
||||
|
||||
# Where templates live |
||||
TEMPLATEDIR = '.' |
||||
|
||||
# Where rendered templates will go |
||||
OUTDIR = 'output' |
||||
|
||||
# Should existing (destination) files |
||||
# be overwritten if they exist? |
||||
OVERWRITE = True |
||||
|
||||
# Template variables |
||||
TV = { |
||||
'server_name_default': 'charlesreid1.red', |
||||
'username': 'charles', |
||||
'webhooks_install_dir' : '/home/charles/pod-webhooks' |
||||
} |
||||
|
||||
|
||||
|
||||
def apply_templates(template_dir, output_dir, template_vars, overwrite=False): |
||||
"""Apply the template variables |
||||
to the template files. |
||||
""" |
||||
|
||||
if not os.path.exists(output_dir): |
||||
msg = "Error: output dir %s does not exist!"%(output_dir) |
||||
raise Exception(msg) |
||||
|
||||
if not os.path.exists(template_dir): |
||||
msg = "Error: template dir %s does not exist!"%(output_dir) |
||||
raise Exception(msg) |
||||
|
||||
# Jinja env |
||||
env = Environment(loader=FileSystemLoader('.')) |
||||
|
||||
# Render templates |
||||
template_files = glob.glob('captain*.j2') |
||||
render_files = [re.sub('\.j2','',s) for s in template_files] |
||||
|
||||
for rfile,tfile in zip(render_files,template_files): |
||||
|
||||
# Get rendered template content |
||||
content = env.get_template(tfile).render(**template_vars) |
||||
|
||||
# Write to file |
||||
dest = os.path.join(output_dir,rfile) |
||||
if os.path.exists(dest) and overwrite is False: |
||||
msg = "Error: template rendering destination %s already exists!"%(dest) |
||||
raise Exception(msg) |
||||
|
||||
with open(dest,'w') as f: |
||||
f.write(content) |
||||
|
||||
print("Rendered the following templates:%s\nOutput files:%s\n"%( |
||||
"".join(["\n- "+os.path.join(template_dir,j) for j in template_files]), |
||||
"".join(["\n- "+os.path.join(output_dir,j) for j in render_files]) |
||||
)) |
||||
|
||||
|
||||
if __name__=="__main__": |
||||
apply_templates(TEMPLATEDIR,OUTDIR,TV,OVERWRITE) |
||||
|
@ -0,0 +1,84 @@
@@ -0,0 +1,84 @@
|
||||
import os, re, sys |
||||
import glob |
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape |
||||
|
||||
""" |
||||
Apply Default Values to |
||||
pod-webhooks Jinja Templates |
||||
|
||||
|
||||
This script applies default values to |
||||
templates in this folder. |
||||
|
||||
The templates are used by Ansible, |
||||
but this script uses the same template |
||||
engine as Ansible to apply template |
||||
variable values to the template files |
||||
and make real files. |
||||
|
||||
variables are: |
||||
- `webhooks_install_dir` - location of pod-webhooks repo |
||||
(i.e., location of pod-webhooks docker-compose file) |
||||
""" |
||||
|
||||
|
||||
# Where templates live |
||||
TEMPLATEDIR = '.' |
||||
|
||||
# Where rendered templates will go |
||||
OUTDIR = 'output' |
||||
|
||||
# Should existing (destination) files |
||||
# be overwritten if they exist? |
||||
OVERWRITE = True |
||||
|
||||
# Template variables |
||||
TV = { |
||||
'webhooks_install_dir' : '/home/charles/pod-webhooks' |
||||
} |
||||
|
||||
|
||||
|
||||
def apply_templates(template_dir, output_dir, template_vars, overwrite=False): |
||||
"""Apply the template variables |
||||
to the template files. |
||||
""" |
||||
|
||||
if not os.path.exists(output_dir): |
||||
msg = "Error: output dir %s does not exist!"%(output_dir) |
||||
raise Exception(msg) |
||||
|
||||
if not os.path.exists(template_dir): |
||||
msg = "Error: template dir %s does not exist!"%(output_dir) |
||||
raise Exception(msg) |
||||
|
||||
# Jinja env |
||||
env = Environment(loader=FileSystemLoader('.')) |
||||
|
||||
# Render templates |
||||
template_files = glob.glob('*.service.j2') |
||||
render_files = [re.sub('\.j2','',s) for s in template_files] |
||||
|
||||
for rfile,tfile in zip(render_files,template_files): |
||||
|
||||
# Get rendered template content |
||||
content = env.get_template(tfile).render(**template_vars) |
||||
|
||||
# Write to file |
||||
dest = os.path.join(output_dir,rfile) |
||||
if os.path.exists(dest) and overwrite is False: |
||||
msg = "Error: template rendering destination %s already exists!"%(dest) |
||||
raise Exception(msg) |
||||
|
||||
with open(dest,'w') as f: |
||||
f.write(content) |
||||
|
||||
print("Rendered the following templates:%s\nOutput files:%s\n"%( |
||||
"".join(["\n- "+os.path.join(template_dir,j) for j in template_files]), |
||||
"".join(["\n- "+os.path.join(output_dir,j) for j in render_files]) |
||||
)) |
||||
|
||||
|
||||
if __name__=="__main__": |
||||
apply_templates(TEMPLATEDIR,OUTDIR,TV,OVERWRITE) |
||||
|
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
import os, re, sys |
||||
import glob |
||||
import subprocess |
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape |
||||
|
||||
""" |
||||
Apply Default Values to |
||||
SUBDOMAINS Jinja Templates |
||||
|
||||
|
||||
This script applies default values to |
||||
templates in this folder. |
||||
|
||||
The templates are used by Ansible, |
||||
but this script uses the same template |
||||
engine as Ansible to apply template |
||||
variable values to the template files |
||||
and make real files. |
||||
|
||||
only variables are: |
||||
- `username` - user/group name to change ownership to |
||||
- `server_name_default` - name of server |
||||
(e.g., charlesreid1.com or charlesreid1.red) |
||||
""" |
||||
|
||||
|
||||
# Where templates live |
||||
TEMPLATEDIR = '.' |
||||
|
||||
# Where rendered templates will go |
||||
OUTDIR = 'output' |
||||
|
||||
# Should existing (destination) files |
||||
# be overwritten if they exist? |
||||
OVERWRITE = True |
||||
|
||||
# Template variables |
||||
TV = { |
||||
'server_name_default': 'charlesreid1.red', |
||||
'username': 'charles' |
||||
} |
||||
|
||||
|
||||
|
||||
def apply_templates(template_dir, output_dir, template_vars, overwrite=False): |
||||
"""Apply the template variables |
||||
to the template files. |
||||
""" |
||||
|
||||
if not os.path.exists(output_dir): |
||||
msg = "Error: output dir %s does not exist!"%(output_dir) |
||||
raise Exception(msg) |
||||
|
||||
if not os.path.exists(template_dir): |
||||
msg = "Error: template dir %s does not exist!"%(output_dir) |
||||
raise Exception(msg) |
||||
|
||||
# Jinja env |
||||
env = Environment(loader=FileSystemLoader('.')) |
||||
|
||||
# Render templates |
||||
template_files = glob.glob('*_setup.py.j2') + glob.glob('*_pull.py.j2') |
||||
render_files = [re.sub('\.j2','',s) for s in template_files] |
||||
|
||||
for rfile,tfile in zip(render_files,template_files): |
||||
|
||||
# Get rendered template content |
||||
content = env.get_template(tfile).render(**template_vars) |
||||
|
||||
# Write to file |
||||
dest = os.path.join(output_dir,rfile) |
||||
if os.path.exists(dest) and overwrite is False: |
||||
msg = "Error: template rendering destination %s already exists!"%(dest) |
||||
raise Exception(msg) |
||||
|
||||
with open(dest,'w') as f: |
||||
f.write(content) |
||||
|
||||
x = 'executioner.py' |
||||
subprocess.call(['cp',x,os.path.join(output_dir,x)]) |
||||
|
||||
print("Rendered the following templates:%s\nOutput files:%s\n"%( |
||||
"".join(["\n- "+os.path.join(template_dir,j) for j in template_files]), |
||||
"".join(["\n- "+os.path.join(output_dir,j) for j in render_files]) |
||||
)) |
||||
|
||||
|
||||
if __name__=="__main__": |
||||
apply_templates(TEMPLATEDIR,OUTDIR,TV,OVERWRITE) |
||||
|
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
[Unit] |
||||
Description=captain hook canary script |
||||
Requires=pod-webhooks.service |
||||
After=pod-webhooks.service |
||||
|
||||
[Service] |
||||
Restart=always |
||||
ExecStart={{ webhooks_install_dir }}/scripts/captain_hook_canary.sh |
||||
ExecStop=/usr/bin/pgrep -f captain_hook_canary | /usr/bin/xargs /bin/kill |
||||
|
||||
[Install] |
||||
WantedBy=default.target |
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash |
||||
|
||||
: ' |
||||
Captain Hook Canary Script (Template) |
||||
|
||||
|
||||
Note: this needs an associated systemd service. |
||||
See the services directory of the dotfiles repo. |
||||
|
||||
This is a canary script for connecting |
||||
the Captain Hook container to the host |
||||
machine, and triggering tasks on the |
||||
host machine with webhooks. |
||||
|
||||
The Captain Hook container mounts the |
||||
following host directory inside the |
||||
container (same location for host/container): |
||||
|
||||
/tmp/triggers/ |
||||
|
||||
When a webhook in Captain Hook wants to |
||||
trigger an event on the host (blackbeard), |
||||
it puts a file in /tmp/triggers/. |
||||
|
||||
Meanwhile, on the host, this script checks |
||||
every 10 seconds for trigger files. |
||||
|
||||
Each webhook can create its own trigger file, |
||||
and this script processes each trigger differently. |
||||
' |
||||
|
||||
while true |
||||
do |
||||
# bootstrap-pull captain hook |
||||
if [ -f "/tmp/triggers/push-b-captain-hook-master" ]; then |
||||
echo "CAPTAIN HOOK'S CANARY:" |
||||
echo "Running trigger to update Captain Hook on the host machine (user charles)" |
||||
sudo -H -u charles python {{ webhooks_install_dir }}/scripts/captain_hook_pull_host.py |
||||
echo "All done." |
||||
rm -f "/tmp/triggers/push-b-captain-hook-master" |
||||
touch /tmp/canary-yup-host-works |
||||
fi |
||||
|
||||
sleep 10; |
||||
done |
||||
|
||||
|
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python3 |
||||
import subprocess |
||||
import os |
||||
import time |
||||
|
||||
""" |
||||
Captain Hook: Pull Captain Hook on the Host |
||||
|
||||
This script is called by the host machine |
||||
(blackbeard) running the Captain Hook container. |
||||
|
||||
This is triggered by push actions to the |
||||
master branch of b-captain-hook. |
||||
|
||||
The action is to update (git pull) the copy |
||||
of Captain Hook running on the host, and |
||||
restart the container pod. |
||||
""" |
||||
|
||||
pod_dir = '{{ webhooks_install_dir }}' |
||||
work_dir = os.path.join(pod_dir,'b-captain-hook') |
||||
|
||||
from datetime import datetime |
||||
d = datetime.now().strftime('%Y-m-%d') |
||||
with open('/tmp/captain_hook_pull_host_%s.log'%(d),'w') as f: |
||||
|
||||
# Step 1: |
||||
# Update Captain Hook |
||||
co_cmd = ['git','checkout','master'] |
||||
proc = subprocess.call(co_cmd, cwd=work_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
||||
|
||||
stdout, stderr = proc.communicate() |
||||
o = stdout.decode('utf-8') |
||||
e = stderr.decode('utf-8') |
||||
f.write(" ".join(co_cmd)) |
||||
f.write("\n") |
||||
f.write("-"*40) |
||||
f.write("\n") |
||||
f.write(o) |
||||
f.write("\n") |
||||
f.write(e) |
||||
f.write("\n\n") |
||||
|
||||
f_cmd = ['git','fetch','--all'] |
||||
proc = subprocess.call(f_cmd, cwd=work_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
||||
|
||||
stdout, stderr = proc.communicate() |
||||
o = stdout.decode('utf-8') |
||||
e = stderr.decode('utf-8') |
||||
f.write(" ".join(f_cmd)) |
||||
f.write("\n") |
||||
f.write("-"*40) |
||||
f.write("\n") |
||||
f.write(o) |
||||
f.write("\n") |
||||
f.write(e) |
||||
f.write("\n\n") |
||||
time.sleep(5) |
||||
|
||||
pull_cmd = ['git','pull','origin','master'] |
||||
proc = subprocess.call(pull_cmd, cwd=work_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
||||
|
||||
stdout, stderr = proc.communicate() |
||||
o = stdout.decode('utf-8') |
||||
e = stderr.decode('utf-8') |
||||
f.write(" ".join(pull_cmd)) |
||||
f.write("\n") |
||||
f.write("-"*40) |
||||
f.write("\n") |
||||
f.write(o) |
||||
f.write("\n") |
||||
f.write(e) |
||||
f.write("\n\n") |
||||
time.sleep(10) |
||||
|
||||
submod_cmd = ['git','submodule','update','--remote'] |
||||
proc = subprocess.call(submod_cmd, cwd=work_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
||||
|
||||
stdout, stderr = proc.communicate() |
||||
o = stdout.decode('utf-8') |
||||
e = stderr.decode('utf-8') |
||||
f.write(" ".join(pull_cmd)) |
||||
f.write("\n") |
||||
f.write("-"*40) |
||||
f.write("\n") |
||||
f.write(o) |
||||
f.write("\n") |
||||
f.write(e) |
||||
f.write("\n\n") |
||||
time.sleep(10) |
||||
|
||||
|
||||
# Step 2: |
||||
# Restart Captain Hook pod |
||||
pod_restart = ['systemctl','restart','pod-webhooks'] |
||||
#pod_restart = ['docker-compose','restart'] |
||||
proc = subprocess.call(pod_restart, cwd=pod_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
||||
|
||||
stdout, stderr = proc.communicate() |
||||
o = stdout.decode('utf-8') |
||||
e = stderr.decode('utf-8') |
||||
f.write(" ".join(pod_restart)) |
||||
f.write("\n") |
||||
f.write("-"*40) |
||||
f.write("\n") |
||||
f.write(o) |
||||
f.write("\n") |
||||
f.write(e) |
||||
f.write("\n\n") |
||||
|
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python3 |
||||
import subprocess |
||||
import os |
||||
|
||||
def execute(cmd): |
||||
""" |
||||
A function to run a command and return the |
||||
lines of output as they are generated, |
||||
allowing the calling function to "stream" |
||||
the output of the command to print() or etc. |
||||
""" |
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) |
||||
for stdout_line in iter(p.stdout.readline, ""): |
||||
yield stdout_line |
||||
p.stdout.close() |
||||
err = "".join([j for j in iter(p.stderr.readline,"")]) |
||||
return_code = p.wait() |
||||
if return_code: |
||||
yield err |
||||
raise subprocess.CalledProcessError(return_code, cmd) |
||||
|
@ -0,0 +1,125 @@
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env python3 |
||||
import subprocess |
||||
import os |
||||
from executioner import execute |
||||
|
||||
""" |
||||
Pages Initial Setup |
||||
|
||||
This script sets up the initial pages.charlesreid1.XYZ |
||||
folder structure and checks out all pages that should |
||||
be present initially at pages.charlesreid1.XYZ. |
||||
|
||||
This clones the page for a given project to |
||||
|
||||
/www/pages.charlesreid1.XYZ/htdocs/project-name |
||||
|
||||
(where project = repo) |
||||
""" |
||||
|
||||
SERVER_NAME_DEFAULT = '{{ server_name_default }}' |
||||
USERNAME = '{{ username }}' |
||||
|
||||
|
||||
|
||||
# Repos must have a gh-pages branch |
||||
repo_names = '''bots/b-apollo |
||||
bots/b-captain-hook |
||||
bots/b-ginsberg |
||||
bots/b-milton |
||||
bots/uncle-archie |
||||
bots/boring-mind-machine |
||||
docker/d-gitea |
||||
docker/d-mediawiki |
||||
docker/d-mysql |
||||
docker/d-nginx-charlesreid1 |
||||
docker/d-nginx-subdomains |
||||
docker/d-phpmyadmin |
||||
docker/d-python-files |
||||
docker/d-python-helium |
||||
charlesreid1/dont-sudo-pip |
||||
bots/embarcadero-mind-machine |
||||
charlesreid1/git-commit-ectomy |
||||
charlesreid1/git-subway-maps |
||||
charlesreid1/github-heroku-attack-rabbits |
||||
charlesreid1/how-do-i-heroku |
||||
charlesreid1/how-do-i-pandoc |
||||
charlesreid1/how-do-i-pelican |
||||
charlesreid1/how-do-i-pyenv |
||||
charlesreid1/how-do-i-snakemake |
||||
docker/pod-bots |
||||
docker/pod-charlesreid1 |
||||
docker/pod-webhooks |
||||
bots/russian-rainbow-mind-machine |
||||
charlesreid1/scurvy-knave-theme |
||||
charlesreid1/translate-yer-docs |
||||
charlesreid1/wisko-manual'''.split('\n') |
||||
|
||||
repo_urls = ['https://git.charlesreid1.com/%s.git'%(j) for j in repo_names] |
||||
|
||||
root = '/www' |
||||
pages = 'pages.%s'%(SERVER_NAME_DEFAULT) |
||||
basedir = os.path.join(root,pages) |
||||
|
||||
if not os.path.exists(basedir): |
||||
raise Exception("Error: base directory %s does not exist!"%(basedir)) |
||||
|
||||
for name,url in zip(repo_names,repo_urls): |
||||
|
||||
# for a hypothetical repo "project": |
||||
# |
||||
# base dir: /www/pages.charlesreid1.com |
||||
# .git dir: /www/pages.charlesreid1.com/git.project |
||||
# htdocs dir: /www/pages.charlesreid1.com/htdocs/project |
||||
|
||||
# Step 1: clone |
||||
# Construct the clone command to set up |
||||
# live htdocs directory for this project |
||||
|
||||
repo_owner, repo_name = name.split("/") |
||||
|
||||
clonepth = os.path.join(basedir,"htdocs",repo_name) |
||||
dotgitpth = os.path.join(basedir,"git.%s"%(repo_name)) |
||||
|
||||
if os.path.exists(clonepth): |
||||
print("Git repository has already been cloned, %s already exists on disk!"%(clonepth)) |
||||
|
||||
else: |
||||
|
||||
clonecmd = ["git","clone", |
||||
"--separate-git-dir=%s"%(dotgitpth), |
||||
"-b","gh-pages", |
||||
url,clonepth] |
||||
|
||||
print("About to clone gh-pages branch for %s using command:\n"%(name)) |
||||
print(" $ " + " ".join(clonecmd)) |
||||
print("\n") |
||||
|
||||
try: |
||||
for loo in execute(clonecmd): |
||||
print(loo) |
||||
print("\n") |
||||
print("Done.") |
||||
|
||||
except subprocess.CalledProcessError: |
||||
print("Failed on clone command for project %s"%(name)) |
||||
print("Continuing...") |
||||
|
||||
|
||||
|
||||
# Step 2: chown everybody |
||||
# Construct chown command |
||||
chowncmd = ['chown','-R', |
||||
USERNAME+":"+USERNAME, |
||||
basedir] |
||||
|
||||
print("About to change owner of %s using command:\n"%(basedir)) |
||||
print(" $ " + " ".join(chowncmd)) |
||||
print("\n") |
||||
|
||||
for loo in execute(chowncmd): |
||||
print(loo) |
||||
print("\n") |
||||
|
||||
print("Done.") |
||||
|
@ -0,0 +1,129 @@
@@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env python3 |
||||
import subprocess |
||||
import os |
||||
from executioner import execute |
||||
|
||||
""" |
||||
Pages Pull Script |
||||
|
||||
This script pulls chnages to all repos in the |
||||
pages.charlesreid1.XYZ folder structure |
||||
|
||||
This clones the page for a given project to |
||||
|
||||
/www/pages.charlesreid1.XYZ/htdocs/project-name |
||||
|
||||
(where project = repo) |
||||
""" |
||||
|
||||
SERVER_NAME_DEFAULT = '{{ server_name_default }}' |
||||
USERNAME = '{{ username }}' |
||||
|
||||
|
||||
|
||||
# Repos must have a gh-pages branch |
||||
repo_names = '''bots/b-apollo |
||||
bots/b-captain-hook |
||||
bots/b-ginsberg |
||||
bots/b-milton |
||||
bots/uncle-archie |
||||
bots/boring-mind-machine |
||||
docker/d-gitea |
||||
docker/d-mediawiki |
||||
docker/d-mysql |
||||
docker/d-nginx-charlesreid1 |
||||
docker/d-nginx-subdomains |
||||
docker/d-phpmyadmin |
||||
docker/d-python-files |
||||
docker/d-python-helium |
||||
charlesreid1/dont-sudo-pip |
||||
bots/embarcadero-mind-machine |
||||
charlesreid1/git-commit-ectomy |
||||
charlesreid1/git-subway-maps |
||||
charlesreid1/github-heroku-attack-rabbits |
||||
charlesreid1/how-do-i-heroku |
||||
charlesreid1/how-do-i-pandoc |
||||
charlesreid1/how-do-i-pelican |
||||
charlesreid1/how-do-i-pyenv |
||||
charlesreid1/how-do-i-snakemake |
||||
docker/pod-bots |
||||
docker/pod-charlesreid1 |
||||
docker/pod-webhooks |
||||
bots/russian-rainbow-mind-machine |
||||
charlesreid1/scurvy-knave-theme |
||||
charlesreid1/translate-yer-docs |
||||
charlesreid1/wisko-manual'''.split('\n') |
||||
|
||||
repo_urls = ['https://git.charlesreid1.com/%s.git'%(j) for j in repo_names] |
||||
|
||||
root = '/www' |
||||
pages = 'pages.%s'%(SERVER_NAME_DEFAULT) |
||||
basedir = os.path.join(root,pages) |
||||
htdocsdir = os.path.join(basedir,"htdocs") |
||||
|
||||
if not os.path.exists(basedir): |
||||
raise Exception("Error: base directory %s does not exist!"%(basedir)) |
||||
|
||||
if not os.path.exists(htdocsdir): |
||||
raise Exception("Error: htdocs directory %s does not exist!"%(htdocsdir)) |
||||
|
||||
for name,url in zip(repo_names,repo_urls): |
||||
|
||||
# for a hypothetical repo "project": |
||||
# |
||||
# base dir: /www/pages.charlesreid1.com |
||||
# .git dir: /www/pages.charlesreid1.com/git.project |
||||
# htdocs dir: /www/pages.charlesreid1.com/htdocs/project |
||||
|
||||
# Step 1: pull |
||||
# Construct the git pull command to update |
||||
# the live htdocs directory for this project |
||||
|
||||
repo_owner, repo_name = name.split("/") |
||||
|
||||
workdir = os.path.join(basedir,"htdocs",repo_name) |
||||
dotgitdir = os.path.join(basedir,"git.%s"%(repo_name)) |
||||
|
||||
if not os.path.exists(workdir): |
||||
print("Git repository has not yet been cloned, %s does not exist on disk!"%(workdir)) |
||||
|
||||
else: |
||||
|
||||
pullcmd = ['git', |
||||
'-C', basedir, |
||||
'--git-dir=%s'%(dotgitdir), |
||||
'--work-tree=%s'%(workdir), |
||||
'pull','origin','gh-pages'] |
||||
|
||||
print("About to pull gh-pages branch for %s using command:\n"%(name)) |
||||
print(" $ " + " ".join(pullcmd)) |
||||
print("\n") |
||||
|
||||
try: |
||||
for loo in execute(pullcmd): |
||||
print(loo) |
||||
print("\n") |
||||
print("Done.") |
||||
|
||||
except subprocess.CalledProcessError: |
||||
print("Failed on pull command for project %s"%(name)) |
||||
print("Continuing...") |
||||
|
||||
|
||||
|
||||
# Step 2: chown everybody |
||||
# Construct chown command |
||||
chowncmd = ['chown','-R', |
||||
USERNAME+":"+USERNAME, |
||||
basedir] |
||||
|
||||
print("About to change owner of %s using command:\n"%(basedir)) |
||||
print(" $ " + " ".join(chowncmd)) |
||||
print("\n") |
||||
|
||||
for loo in execute(chowncmd): |
||||
print(loo) |
||||
print("\n") |
||||
|
||||
print("Done.") |
||||
|
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
# Hopefully this comment works |
||||
|
||||
[Unit] |
||||
Description=webhooks and subdomains docker pod |
||||
Requires=docker.service |
||||
After=docker.service |
||||
|
||||
[Service] |
||||
Restart=always |
||||
ExecStart=/usr/local/bin/docker-compose -f {{ webhooks_install_dir }}/docker-compose.yml up |
||||
ExecStop=/usr/local/bin/docker-compose -f {{ webhooks_install_dir }}/docker-compose.yml down |
||||
|
||||
[Install] |
||||
WantedBy=default.target |
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3 |
||||
import subprocess |
||||
import os |
||||
from executioner import execute |
||||
|
||||
""" |
||||
Subdomains Initial Setup |
||||
|
||||
This script sets up the initial folder structure |
||||
for the charlesreid1.com subdomains and their content. |
||||
""" |
||||
|
||||
SERVER_NAME_DEFAULT = '{{ server_name_default }}' |
||||
USERNAME = '{{ username }}' |
||||
|
||||
|
||||
|
||||
# Each subdomain page has an htdocs dir at |
||||
# |
||||
# /www/SUBDOMAIN.charlesreid1.XYZ/htdocs |
||||
# |
||||
# and a .git directory at |
||||
# |
||||
# /www/SUBDOMAIN.charlesreid1.XYZ/git.SUBDOMAIN.charlesreid1.XYZ |
||||
|
||||
# Name of all subdomains to set up |
||||
sub_names = ['bots','pages','hooks'] |
||||
subs = [n+'.'+SERVER_NAME_DEFAULT for n in sub_names] |
||||
|
||||
# Use git.charlesreid1.com |
||||
# (Note we have to hard-code the suffix |
||||
# charlesreid1.com b/c that is the name |
||||
# of the repo for ALL subdomains) |
||||
urls = ['https://git.charlesreid1.com/charlesreid1/%s.charlesreid1.com'%(n) for n in sub_names] |
||||
# |
||||
# Use github.com (alternative) |
||||
# (Note we have to hard-code the suffix charlesreid1.com) |
||||
#urls = ['https://github.com/charlesreid1-docker/%s.charlesreid1.com'%(n) for n in sub_names] |
||||
|
||||
# Base directory for all htdocs folders |
||||
pth = '/www' |
||||
|
||||
# Create the base directory |
||||
subprocess.call(['mkdir','-p',pth]) |
||||
|
||||
# Step 1: clone htdocs dir for each subdomain |
||||
for subname, sub, url in zip(sub_names,subs,urls): |
||||
|
||||
# Construct the clone command for the live |
||||
# htdocs directory for this subdomain |
||||
clonepth = os.path.join(pth,sub,'htdocs') |
||||
dotgitpth = os.path.join(pth,sub,'git.%s'%(subname)) |
||||
|
||||
if os.path.exists(clonepth): |
||||
print("Git repository has already been cloned, %s already exists on disk!"%(clonepth)) |
||||
|
||||
else: |
||||
|
||||
clonecmd = ['git','clone', |
||||
'--separate-git-dir=%s'%(dotgitpth), |
||||
'-b','gh-pages', |
||||
url,clonepth] |
||||
|
||||
print("About to clone htdocs dir for %s using command:\n"%(sub)) |
||||
print(" $ " + " ".join(clonecmd)) |
||||
print("\n") |
||||
|
||||
for loo in execute(clonecmd): |
||||
print(loo) |
||||
print("\n") |
||||
|
||||
print("Done.") |
||||
|
||||
|
||||
|
||||
# Step 2: chown |
||||
# Construct chown command to chown everybody |
||||
chowncmd = ['chown','-R',USERNAME+":"+USERNAME,pth] |
||||
|
||||
print("About to change owner of %s using command:\n"%(pth)) |
||||
print(" $ " + " ".join(chowncmd)) |
||||
print("\n") |
||||
|
||||
for loo in execute(chowncmd): |
||||
print(loo) |
||||
print("\n") |
||||
|
||||
print("Done.") |
||||
|
@ -0,0 +1,95 @@
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python3 |
||||
import subprocess |
||||
import os |
||||
from executioner import execute |
||||
|
||||
""" |
||||
Subdomains Pull Script |
||||
|
||||
This script sets up the initial folder structure |
||||
for the charlesreid1.com subdomains and their content. |
||||
""" |
||||
|
||||
SERVER_NAME_DEFAULT = '{{ server_name_default }}' |
||||
USERNAME = '{{ username }}' |
||||
|
||||
|
||||
|
||||
# Each subdomain page has an htdocs dir at |
||||
# |
||||
# /www/SUBDOMAIN.charlesreid1.XYZ/htdocs |
||||
# |
||||
# and a .git directory at |
||||
# |
||||
# /www/SUBDOMAIN.charlesreid1.XYZ/git.SUBDOMAIN.charlesreid1.XYZ |
||||
|
||||
# Name of all subdomains to set up |
||||
sub_names = ['bots','pages','hooks'] |
||||
subs = [n+'.'+SERVER_NAME_DEFAULT for n in sub_names] |
||||
|
||||
# Use git.charlesreid1.com |
||||
# (Note we have to hard-code the suffix |
||||
# charlesreid1.com b/c that is the name |
||||
# of the repo for ALL subdomains) |
||||
urls = ['https://git.charlesreid1.com/charlesreid1/%s.charlesreid1.com'%(n) for n in sub_names] |
||||
# |
||||
# Use github.com (alternative) |
||||
# (Note we have to hard-code the suffix charlesreid1.com) |
||||
#urls = ['https://github.com/charlesreid1-docker/%s.charlesreid1.com'%(n) for n in sub_names] |
||||
|
||||
# Base directory for all htdocs folders |
||||
pth = '/www' |
||||
|
||||
# Create the base directory |
||||
subprocess.call(['mkdir','-p',pth]) |
||||
|
||||
# Step 1: clone htdocs dir for each subdomain |
||||
for subname, sub, url in zip(sub_names,subs,urls): |
||||
|
||||
# Step 1: pull |
||||
# Construct the git pull command to update |
||||
# the live htdocs directory for this project |
||||
|
||||
basedir = os.path.join(pth,sub) |
||||
htdocsdir = os.path.join(basedir,"htdocs") |
||||
dotgitdir = os.path.join(basedir,"git.%s"%(subname)) |
||||
|
||||
if not os.path.exists(htdocsdir): |
||||
print("Git repository has not been cloned, %s does not exist on disk!"%(htdocsdir)) |
||||
|
||||
else: |
||||
|
||||
# git pull, respecting the |
||||
# unusual .git/repo folder layout |
||||
pullcmd = ['git', |
||||
'-C', basedir, |
||||
'--git-dir=%s'%(dotgitdir), |
||||
'--work-tree=%s'%(htdocsdir), |
||||
'pull','origin','gh-pages'] |
||||
|
||||
|
||||
print("About to pull htdocs dir for %s using command:\n"%(sub)) |
||||
print(" $ " + " ".join(pullcmd)) |
||||
print("\n") |
||||
|
||||
for loo in execute(pullcmd): |
||||
print(loo) |
||||
print("\n") |
||||
print("Done.") |
||||
|
||||
|
||||
|
||||
# Step 2: chown |
||||
# Construct chown command to chown everybody |
||||
chowncmd = ['chown','-R',USERNAME+":"+USERNAME,basedir] |
||||
|
||||
print("About to change owner of %s using command:\n"%(basedir)) |
||||
print(" $ " + " ".join(chowncmd)) |
||||
print("\n") |
||||
|
||||
for loo in execute(chowncmd): |
||||
print(loo) |
||||
print("\n") |
||||
|
||||
print("Done.") |
||||
|
@ -1,96 +0,0 @@
@@ -1,96 +0,0 @@
|
||||
function getSearchTermFromLocation() { |
||||
var sPageURL = window.location.search.substring(1); |
||||
var sURLVariables = sPageURL.split('&'); |
||||
for (var i = 0; i < sURLVariables.length; i++) { |
||||
var sParameterName = sURLVariables[i].split('='); |
||||
if (sParameterName[0] == 'q') { |
||||
return decodeURIComponent(sParameterName[1].replace(/\+/g, '%20')); |
||||
} |
||||
} |
||||
} |
||||
|
||||
function joinUrl (base, path) { |
||||
if (path.substring(0, 1) === "/") { |
||||
// path starts with `/`. Thus it is absolute.
|
||||
return path; |
||||
} |
||||
if (base.substring(base.length-1) === "/") { |
||||
// base ends with `/`
|
||||
return base + path; |
||||
} |
||||
return base + "/" + path; |
||||
} |
||||
|
||||
function formatResult (location, title, summary) { |
||||
return '<article><h3><a href="' + joinUrl(base_url, location) + '">'+ title + '</a></h3><p>' + summary +'</p></article>'; |
||||
} |
||||
|
||||
function displayResults (results) { |
||||
var search_results = document.getElementById("mkdocs-search-results"); |
||||
while (search_results.firstChild) { |
||||
search_results.removeChild(search_results.firstChild); |
||||
} |
||||
if (results.length > 0){ |
||||
for (var i=0; i < results.length; i++){ |
||||
var result = results[i]; |
||||
var html = formatResult(result.location, result.title, result.summary); |
||||
search_results.insertAdjacentHTML('beforeend', html); |
||||
} |
||||
} else { |
||||
search_results.insertAdjacentHTML('beforeend', "<p>No results found</p>"); |
||||
} |
||||
} |
||||
|
||||
function doSearch () { |
||||
var query = document.getElementById('mkdocs-search-query').value; |
||||
if (query.length > 2) { |
||||
if (!window.Worker) { |
||||
displayResults(search(query)); |
||||
} else { |
||||
searchWorker.postMessage({query: query}); |
||||
} |
||||
} else { |
||||
// Clear results for short queries
|
||||
displayResults([]); |
||||
} |
||||
} |
||||
|
||||
function initSearch () { |
||||
var search_input = document.getElementById('mkdocs-search-query'); |
||||
if (search_input) { |
||||
search_input.addEventListener("keyup", doSearch); |
||||
} |
||||
var term = getSearchTermFromLocation(); |
||||
if (term) { |
||||
search_input.value = term; |
||||
doSearch(); |
||||
} |
||||
} |
||||
|
||||
function onWorkerMessage (e) { |
||||
if (e.data.allowSearch) { |
||||
initSearch(); |
||||
} else if (e.data.results) { |
||||
var results = e.data.results; |
||||
displayResults(results); |
||||
} |
||||
} |
||||
|
||||
if (!window.Worker) { |
||||
console.log('Web Worker API not supported'); |
||||
// load index in main thread
|
||||
$.getScript(joinUrl(base_url, "search/worker.js")).done(function () { |
||||
console.log('Loaded worker'); |
||||
init(); |
||||
window.postMessage = function (msg) { |
||||
onWorkerMessage({data: msg}); |
||||
}; |
||||
}).fail(function (jqxhr, settings, exception) { |
||||
console.error('Could not load worker.js'); |
||||
}); |
||||
} else { |
||||
// Wrap search in a web worker
|
||||
var searchWorker = new Worker(joinUrl(base_url, "search/worker.js")); |
||||
searchWorker.postMessage({init: true}); |
||||
searchWorker.onmessage = onWorkerMessage; |
||||
} |
File diff suppressed because one or more lines are too long
@ -1,128 +0,0 @@
@@ -1,128 +0,0 @@
|
||||
var base_path = 'function' === typeof importScripts ? '.' : '/search/'; |
||||
var allowSearch = false; |
||||
var index; |
||||
var documents = {}; |
||||
var lang = ['en']; |
||||
var data; |
||||
|
||||
function getScript(script, callback) { |
||||
console.log('Loading script: ' + script); |
||||
$.getScript(base_path + script).done(function () { |
||||
callback(); |
||||
}).fail(function (jqxhr, settings, exception) { |
||||
console.log('Error: ' + exception); |
||||
}); |
||||
} |
||||
|
||||
function getScriptsInOrder(scripts, callback) { |
||||
if (scripts.length === 0) { |
||||
callback(); |
||||
return; |
||||
} |
||||
getScript(scripts[0], function() { |
||||
getScriptsInOrder(scripts.slice(1), callback); |
||||
}); |
||||
} |
||||
|
||||
function loadScripts(urls, callback) { |
||||
if( 'function' === typeof importScripts ) { |
||||
importScripts.apply(null, urls); |
||||
callback(); |
||||
} else { |
||||
getScriptsInOrder(urls, callback); |
||||
} |
||||
} |
||||
|
||||
function onJSONLoaded () { |
||||
data = JSON.parse(this.responseText); |
||||
var scriptsToLoad = ['lunr.js']; |
||||
if (data.config && data.config.lang && data.config.lang.length) { |
||||
lang = data.config.lang; |
||||
} |
||||
if (lang.length > 1 || lang[0] !== "en") { |
||||
scriptsToLoad.push('lunr.stemmer.support.js'); |
||||
if (lang.length > 1) { |
||||
scriptsToLoad.push('lunr.multi.js'); |
||||
} |
||||
for (var i=0; i < lang.length; i++) { |
||||
if (lang[i] != 'en') { |
||||
scriptsToLoad.push(['lunr', lang[i], 'js'].join('.')); |
||||
} |
||||
} |
||||
} |
||||
loadScripts(scriptsToLoad, onScriptsLoaded); |
||||
} |
||||
|
||||
function onScriptsLoaded () { |
||||
console.log('All search scripts loaded, building Lunr index...'); |
||||
if (data.config && data.config.separator && data.config.separator.length) { |
||||
lunr.tokenizer.separator = new RegExp(data.config.separator); |
||||
} |
||||
if (data.index) { |
||||
index = lunr.Index.load(data.index); |
||||
data.docs.forEach(function (doc) { |
||||
documents[doc.location] = doc; |
||||
}); |
||||
console.log('Lunr pre-built index loaded, search ready'); |
||||
} else { |
||||
index = lunr(function () { |
||||
if (lang.length === 1 && lang[0] !== "en" && lunr[lang[0]]) { |
||||
this.use(lunr[lang[0]]); |
||||
} else if (lang.length > 1) { |
||||
this.use(lunr.multiLanguage.apply(null, lang)); // spread operator not supported in all browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Browser_compatibility
|
||||
} |
||||
this.field('title'); |
||||
this.field('text'); |
||||
this.ref('location'); |
||||
|
||||
for (var i=0; i < data.docs.length; i++) { |
||||
var doc = data.docs[i]; |
||||
this.add(doc); |
||||
documents[doc.location] = doc; |
||||
} |
||||
}); |
||||
console.log('Lunr index built, search ready'); |
||||
} |
||||
allowSearch = true; |
||||
postMessage({allowSearch: allowSearch}); |
||||
} |
||||
|
||||
function init () { |
||||
var oReq = new XMLHttpRequest(); |
||||
oReq.addEventListener("load", onJSONLoaded); |
||||
var index_path = base_path + '/search_index.json'; |
||||
if( 'function' === typeof importScripts ){ |
||||
index_path = 'search_index.json'; |
||||
} |
||||
oReq.open("GET", index_path); |
||||
oReq.send(); |
||||
} |
||||
|
||||
function search (query) { |
||||
if (!allowSearch) { |
||||
console.error('Assets for search still loading'); |
||||
return; |
||||
} |
||||
|
||||
var resultDocuments = []; |
||||
var results = index.search(query); |
||||
for (var i=0; i < results.length; i++){ |
||||
var result = results[i]; |
||||
doc = documents[result.ref]; |
||||
doc.summary = doc.text.substring(0, 200); |
||||
resultDocuments.push(doc); |
||||
} |
||||
return resultDocuments; |
||||
} |
||||
|
||||
if( 'function' === typeof importScripts ) { |
||||
onmessage = function (e) { |
||||
if (e.data.init) { |
||||
init(); |
||||
} else if (e.data.query) { |
||||
postMessage({ results: search(e.data.query) }); |
||||
} else { |
||||
console.error("Worker - Unrecognized message: " + e); |
||||
} |
||||
}; |
||||
} |
@ -1,28 +0,0 @@
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> |
||||
<url> |
||||
<loc>https://pages.charlesreid1.com/pod-webhooks/</loc> |
||||
<lastmod>2019-03-24</lastmod> |
||||
<changefreq>daily</changefreq> |
||||
</url> |
||||
<url> |
||||
<loc>https://pages.charlesreid1.com/pod-webhooks/adding/</loc> |
||||
<lastmod>2019-03-24</lastmod> |
||||
<changefreq>daily</changefreq> |
||||
</url> |
||||
<url> |
||||
<loc>https://pages.charlesreid1.com/pod-webhooks/running/</loc> |
||||
<lastmod>2019-03-24</lastmod> |
||||
<changefreq>daily</changefreq> |
||||
</url> |
||||
<url> |
||||
<loc>https://pages.charlesreid1.com/pod-webhooks/services/</loc> |
||||
<lastmod>2019-03-24</lastmod> |
||||
<changefreq>daily</changefreq> |
||||
</url> |
||||
<url> |
||||
<loc>https://pages.charlesreid1.com/pod-webhooks/canary/</loc> |
||||
<lastmod>2019-03-24</lastmod> |
||||
<changefreq>daily</changefreq> |
||||
</url> |
||||
</urlset> |
Binary file not shown.
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
# utils-www |
||||
|
||||
`static_clone.py` - clones a repo with a separate git and working dir |
||||
|
||||
`clone_into_volume.sh` - use docker cp and docker exec to copy the above script |
||||
into the container and execute it |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash |
||||
|
||||
NAME="podwebhooks_stormy_captain_hook_1" |
||||
SCRIPT="static_clone.py" |
||||
EXTRA="static_domains.py" |
||||
|
||||
set -x |
||||
|
||||
# copy stuff into container |
||||
docker cp ${SCRIPT} ${NAME}:/tmp/${SCRIPT} |
||||
docker cp ${EXTRA} ${NAME}:/tmp/${EXTRA} |
||||
|
||||
# execute order 66 |
||||
docker exec -it ${NAME} python /tmp/${SCRIPT} |
||||
|
||||
# clean up |
||||
docker exec -it ${NAME} rm -f /tmp/${SCRIPT} /tmp/${EXTRA} |
||||
|
||||
set +x |
||||
|
||||
|
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash |
||||
|
||||
NAME="podwebhooks_stormy_captain_hook_1" |
||||
SCRIPT="static_pull.py" |
||||
EXTRA="static_domains.py" |
||||
|
||||
set -x |
||||
|
||||
# copy stuff into container |
||||
docker cp ${SCRIPT} ${NAME}:/tmp/${SCRIPT} |
||||
docker cp ${EXTRA} ${NAME}:/tmp/${EXTRA} |
||||
|
||||
# execute order 66 |
||||
docker exec -it ${NAME} python /tmp/${SCRIPT} |
||||
|
||||
# clean up |
||||
docker exec -it ${NAME} rm -f /tmp/${SCRIPT} /tmp/${EXTRA} |
||||
|
||||
set +x |
||||
|
||||
|
||||
|
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
import subprocess |
||||
import os |
||||
from static_domains import onepagers |
||||
|
||||
|
||||
if( os.path.isdir('/www') is False ): |
||||
mkdircmd = ["mkdir","/www"] |
||||
subprocess.call(mkdircmd) |
||||
|
||||
for name in onepagers: |
||||
url = onepagers[name] |
||||
|
||||
basedir = os.path.join("/www",name) |
||||
mkdircmd = ["mkdir","-p",basedir] |
||||
clonecmd = ["git","-C",basedir,"clone","--separate-git-dir=git","-b","gh-pages",url,"htdocs"] |
||||
|
||||
if( os.path.isdir( os.path.join(basedir,"git") ) |
||||
and os.path.isdir( os.path.join(basedir,"htdocs")) ): |
||||
print(" ") |
||||
print(" ") |
||||
print("ERROR: The directories /www/%s/git and /www/%s/htodcs"%(name,name)) |
||||
print(" already exist. Use the pull script instead. ") |
||||
print(" ") |
||||
exit(1) |
||||
|
||||
print(" ") |
||||
print("About to run the command:") |
||||
print(" $ " + " ".join(clonecmd)) |
||||
print(" ") |
||||
subprocess.call(mkdircmd) |
||||
subprocess.call(clonecmd) |
||||
|
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
onepagers = { |
||||
'pages.charlesreid1.com' : 'https://git.charlesreid1.com/charlesreid1/pages.charlesreid1.com', |
||||
'hooks.charlesreid1.com' : 'https://git.charlesreid1.com/charlesreid1/hooks.charlesreid1.com', |
||||
'bots.charlesreid1.com' : 'https://git.charlesreid1.com/charlesreid1/bots.charlesreid1.com' |
||||
} |
||||
|
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
import subprocess |
||||
import os |
||||
from static_domains import onepagers |
||||
|
||||
if( os.path.isdir('/www') is False ): |
||||
print(" ") |
||||
print(" ") |
||||
print("ERROR: The /www directory does not exist.") |
||||
print(" Run the clone script instead.") |
||||
print(" ") |
||||
print(" ") |
||||
exit(1) |
||||
|
||||
|
||||
for name in onepagers: |
||||
url = onepagers[name] |
||||
|
||||
basedir = os.path.join("/www",name) |
||||
pullcmd = ["git","-C",basedir,"--git-dir=git","--work-tree=htdocs","pull","origin","gh-pages"] |
||||
|
||||
if( os.path.isdir( os.path.join(basedir,"git") is False ) |
||||
or os.path.isdir( os.path.join(basedir,"htdocs")) is False ): |
||||
print(" ") |
||||
print(" ") |
||||
print("ERROR: The directories /www/%s/git and /www/%s/htodcs"%(name,name)) |
||||
print(" do not exist. Use the clone script instead. ") |
||||
print(" ") |
||||
exit(1) |
||||
|
||||
print(" ") |
||||
print("About to run the command:") |
||||
print(" $ " + " ".join(pullcmd)) |
||||
print(" ") |
||||
subprocess.call(pullcmd) |
||||
|
||||
|
Loading…
Reference in new issue