commit 450f57aac9bf27815749a7d147047bab9689b748 Author: <> Date: Thu Apr 13 21:08:03 2023 +0000 Deployed e017cfe with MkDocs version: 1.4.2 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..3a31ded --- /dev/null +++ b/404.html @@ -0,0 +1,505 @@ + + + + + + + + + + + + + + + + + + + + Infrastructure Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + + +
+
+ +

404 - Not found

+ +
+
+ + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..acda69e --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +infra.rocky.page diff --git a/assets/icon-white.svg b/assets/icon-white.svg new file mode 100644 index 0000000..689ab46 --- /dev/null +++ b/assets/icon-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000..1cf13b9 Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/javascripts/bundle.51198bba.min.js b/assets/javascripts/bundle.51198bba.min.js new file mode 100644 index 0000000..31bd041 --- /dev/null +++ b/assets/javascripts/bundle.51198bba.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Ri=Object.create;var gr=Object.defineProperty;var ki=Object.getOwnPropertyDescriptor;var Hi=Object.getOwnPropertyNames,Ht=Object.getOwnPropertySymbols,Pi=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty,on=Object.prototype.propertyIsEnumerable;var nn=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))yr.call(t,r)&&nn(e,r,t[r]);if(Ht)for(var r of Ht(t))on.call(t,r)&&nn(e,r,t[r]);return e};var an=(e,t)=>{var r={};for(var n in e)yr.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&Ht)for(var n of Ht(e))t.indexOf(n)<0&&on.call(e,n)&&(r[n]=e[n]);return r};var Pt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var $i=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Hi(t))!yr.call(e,o)&&o!==r&&gr(e,o,{get:()=>t[o],enumerable:!(n=ki(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Ri(Pi(e)):{},$i(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var cn=Pt((xr,sn)=>{(function(e,t){typeof xr=="object"&&typeof sn!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(xr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,s={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function a(T){return!!(T&&T!==document&&T.nodeName!=="HTML"&&T.nodeName!=="BODY"&&"classList"in T&&"contains"in T.classList)}function c(T){var Qe=T.type,De=T.tagName;return!!(De==="INPUT"&&s[Qe]&&!T.readOnly||De==="TEXTAREA"&&!T.readOnly||T.isContentEditable)}function f(T){T.classList.contains("focus-visible")||(T.classList.add("focus-visible"),T.setAttribute("data-focus-visible-added",""))}function u(T){T.hasAttribute("data-focus-visible-added")&&(T.classList.remove("focus-visible"),T.removeAttribute("data-focus-visible-added"))}function p(T){T.metaKey||T.altKey||T.ctrlKey||(a(r.activeElement)&&f(r.activeElement),n=!0)}function m(T){n=!1}function d(T){a(T.target)&&(n||c(T.target))&&f(T.target)}function h(T){a(T.target)&&(T.target.classList.contains("focus-visible")||T.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(T.target))}function v(T){document.visibilityState==="hidden"&&(o&&(n=!0),G())}function G(){document.addEventListener("mousemove",N),document.addEventListener("mousedown",N),document.addEventListener("mouseup",N),document.addEventListener("pointermove",N),document.addEventListener("pointerdown",N),document.addEventListener("pointerup",N),document.addEventListener("touchmove",N),document.addEventListener("touchstart",N),document.addEventListener("touchend",N)}function oe(){document.removeEventListener("mousemove",N),document.removeEventListener("mousedown",N),document.removeEventListener("mouseup",N),document.removeEventListener("pointermove",N),document.removeEventListener("pointerdown",N),document.removeEventListener("pointerup",N),document.removeEventListener("touchmove",N),document.removeEventListener("touchstart",N),document.removeEventListener("touchend",N)}function N(T){T.target.nodeName&&T.target.nodeName.toLowerCase()==="html"||(n=!1,oe())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),G(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var fn=Pt(Er=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(f){return!1}},r=t(),n=function(f){var u={next:function(){var p=f.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(f){return encodeURIComponent(f).replace(/%20/g,"+")},i=function(f){return decodeURIComponent(String(f).replace(/\+/g," "))},s=function(){var f=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof f){var d=this;p.forEach(function(oe,N){d.append(N,oe)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),f._entries&&(f._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(c,f){typeof c!="string"&&(c=String(c)),f&&typeof f!="string"&&(f=String(f));var u=document,p;if(f&&(e.location===void 0||f!==e.location.href)){f=f.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=f,u.head.appendChild(p);try{if(p.href.indexOf(f)!==0)throw new Error(p.href)}catch(T){throw new Error("URL unable to set base "+f+" due to "+T)}}var m=u.createElement("a");m.href=c,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=c,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!f)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,G=!0,oe=this;["append","delete","set"].forEach(function(T){var Qe=h[T];h[T]=function(){Qe.apply(h,arguments),v&&(G=!1,oe.search=h.toString(),G=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var N=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==N&&(N=this.search,G&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},s=i.prototype,a=function(c){Object.defineProperty(s,c,{get:function(){return this._anchorElement[c]},set:function(f){this._anchorElement[c]=f},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(c){a(c)}),Object.defineProperty(s,"search",{get:function(){return this._anchorElement.search},set:function(c){this._anchorElement.search=c,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(s,{toString:{get:function(){var c=this;return function(){return c.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(c){this._anchorElement.href=c,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(c){this._anchorElement.pathname=c},enumerable:!0},origin:{get:function(){var c={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],f=this._anchorElement.port!=c&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(f?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(c){},enumerable:!0},username:{get:function(){return""},set:function(c){},enumerable:!0}}),i.createObjectURL=function(c){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(c){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er)});var Kr=Pt((Mt,qr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Mt=="object"&&typeof qr=="object"?qr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Mt=="object"?Mt.ClipboardJS=r():t.ClipboardJS=r()})(Mt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return Ci}});var s=i(279),a=i.n(s),c=i(370),f=i.n(c),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(O){return!1}}var d=function(O){var E=p()(O);return m("cut"),E},h=d;function v(j){var O=document.documentElement.getAttribute("dir")==="rtl",E=document.createElement("textarea");E.style.fontSize="12pt",E.style.border="0",E.style.padding="0",E.style.margin="0",E.style.position="absolute",E.style[O?"right":"left"]="-9999px";var H=window.pageYOffset||document.documentElement.scrollTop;return E.style.top="".concat(H,"px"),E.setAttribute("readonly",""),E.value=j,E}var G=function(O,E){var H=v(O);E.container.appendChild(H);var I=p()(H);return m("copy"),H.remove(),I},oe=function(O){var E=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},H="";return typeof O=="string"?H=G(O,E):O instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(O==null?void 0:O.type)?H=G(O.value,E):(H=p()(O),m("copy")),H},N=oe;function T(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?T=function(E){return typeof E}:T=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},T(j)}var Qe=function(){var O=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},E=O.action,H=E===void 0?"copy":E,I=O.container,q=O.target,Me=O.text;if(H!=="copy"&&H!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&T(q)==="object"&&q.nodeType===1){if(H==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(H==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Me)return N(Me,{container:I});if(q)return H==="cut"?h(q):N(q,{container:I})},De=Qe;function $e(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?$e=function(E){return typeof E}:$e=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},$e(j)}function wi(j,O){if(!(j instanceof O))throw new TypeError("Cannot call a class as a function")}function rn(j,O){for(var E=0;E0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof I.action=="function"?I.action:this.defaultAction,this.target=typeof I.target=="function"?I.target:this.defaultTarget,this.text=typeof I.text=="function"?I.text:this.defaultText,this.container=$e(I.container)==="object"?I.container:document.body}},{key:"listenClick",value:function(I){var q=this;this.listener=f()(I,"click",function(Me){return q.onClick(Me)})}},{key:"onClick",value:function(I){var q=I.delegateTarget||I.currentTarget,Me=this.action(q)||"copy",kt=De({action:Me,container:this.container,target:this.target(q),text:this.text(q)});this.emit(kt?"success":"error",{action:Me,text:kt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(I){return vr("action",I)}},{key:"defaultTarget",value:function(I){var q=vr("target",I);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(I){return vr("text",I)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(I){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return N(I,q)}},{key:"cut",value:function(I){return h(I)}},{key:"isSupported",value:function(){var I=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof I=="string"?[I]:I,Me=!!document.queryCommandSupported;return q.forEach(function(kt){Me=Me&&!!document.queryCommandSupported(kt)}),Me}}]),E}(a()),Ci=Ai},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function s(a,c){for(;a&&a.nodeType!==o;){if(typeof a.matches=="function"&&a.matches(c))return a;a=a.parentNode}}n.exports=s},438:function(n,o,i){var s=i(828);function a(u,p,m,d,h){var v=f.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function c(u,p,m,d,h){return typeof u.addEventListener=="function"?a.apply(null,arguments):typeof m=="function"?a.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return a(v,p,m,d,h)}))}function f(u,p,m,d){return function(h){h.delegateTarget=s(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=c},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var s=Object.prototype.toString.call(i);return i!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var s=Object.prototype.toString.call(i);return s==="[object Function]"}},370:function(n,o,i){var s=i(879),a=i(438);function c(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!s.string(d))throw new TypeError("Second argument must be a String");if(!s.fn(h))throw new TypeError("Third argument must be a Function");if(s.node(m))return f(m,d,h);if(s.nodeList(m))return u(m,d,h);if(s.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function f(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return a(document.body,m,d,h)}n.exports=c},817:function(n){function o(i){var s;if(i.nodeName==="SELECT")i.focus(),s=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var a=i.hasAttribute("readonly");a||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),a||i.removeAttribute("readonly"),s=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var c=window.getSelection(),f=document.createRange();f.selectNodeContents(i),c.removeAllRanges(),c.addRange(f),s=c.toString()}return s}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,s,a){var c=this.e||(this.e={});return(c[i]||(c[i]=[])).push({fn:s,ctx:a}),this},once:function(i,s,a){var c=this;function f(){c.off(i,f),s.apply(a,arguments)}return f._=s,this.on(i,f,a)},emit:function(i){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[i]||[]).slice(),c=0,f=a.length;for(c;c{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var ns=/["'&<>]/;Go.exports=os;function os(e){var t=""+e,r=ns.exec(t);if(!r)return t;var n,o="",i=0,s=0;for(i=r.index;i0&&i[i.length-1])&&(f[0]===6||f[0]===2)){r=0;continue}if(f[0]===3&&(!i||f[1]>i[0]&&f[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],s;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(a){s={error:a}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(s)throw s.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||a(m,d)})})}function a(m,d){try{c(n[m](d))}catch(h){p(i[0][3],h)}}function c(m){m.value instanceof et?Promise.resolve(m.value.v).then(f,u):p(i[0][2],m)}function f(m){a("next",m)}function u(m){a("throw",m)}function p(m,d){m(d),i.shift(),i.length&&a(i[0][0],i[0][1])}}function ln(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof Ee=="function"?Ee(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(s){return new Promise(function(a,c){s=e[i](s),o(a,c,s.done,s.value)})}}function o(i,s,a,c){Promise.resolve(c).then(function(f){i({value:f,done:a})},s)}}function C(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var It=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Ve(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Ie=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var s=this._parentage;if(s)if(this._parentage=null,Array.isArray(s))try{for(var a=Ee(s),c=a.next();!c.done;c=a.next()){var f=c.value;f.remove(this)}}catch(v){t={error:v}}finally{try{c&&!c.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}else s.remove(this);var u=this.initialTeardown;if(C(u))try{u()}catch(v){i=v instanceof It?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=Ee(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{mn(h)}catch(v){i=i!=null?i:[],v instanceof It?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new It(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)mn(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Ve(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Ve(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Sr=Ie.EMPTY;function jt(e){return e instanceof Ie||e&&"closed"in e&&C(e.remove)&&C(e.add)&&C(e.unsubscribe)}function mn(e){C(e)?e():e.unsubscribe()}var Le={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,s=o.isStopped,a=o.observers;return i||s?Sr:(this.currentObservers=null,a.push(r),new Ie(function(){n.currentObservers=null,Ve(a,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,s=n.isStopped;o?r.error(i):s&&r.complete()},t.prototype.asObservable=function(){var r=new F;return r.source=this,r},t.create=function(r,n){return new En(r,n)},t}(F);var En=function(e){ie(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Sr},t}(x);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ie(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,s=n._infiniteTimeWindow,a=n._timestampProvider,c=n._windowTime;o||(i.push(r),!s&&i.push(a.now()+c)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,s=o._buffer,a=s.slice(),c=0;c0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var s=r.actions;n!=null&&((i=s[s.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Wt);var Tn=function(e){ie(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Dt);var Te=new Tn(Sn);var _=new F(function(e){return e.complete()});function Vt(e){return e&&C(e.schedule)}function Cr(e){return e[e.length-1]}function Ye(e){return C(Cr(e))?e.pop():void 0}function Oe(e){return Vt(Cr(e))?e.pop():void 0}function zt(e,t){return typeof Cr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Nt(e){return C(e==null?void 0:e.then)}function qt(e){return C(e[ft])}function Kt(e){return Symbol.asyncIterator&&C(e==null?void 0:e[Symbol.asyncIterator])}function Qt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Ni(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Yt=Ni();function Gt(e){return C(e==null?void 0:e[Yt])}function Bt(e){return pn(this,arguments,function(){var r,n,o,i;return $t(this,function(s){switch(s.label){case 0:r=e.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,et(r.read())];case 3:return n=s.sent(),o=n.value,i=n.done,i?[4,et(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,et(o)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Jt(e){return C(e==null?void 0:e.getReader)}function U(e){if(e instanceof F)return e;if(e!=null){if(qt(e))return qi(e);if(pt(e))return Ki(e);if(Nt(e))return Qi(e);if(Kt(e))return On(e);if(Gt(e))return Yi(e);if(Jt(e))return Gi(e)}throw Qt(e)}function qi(e){return new F(function(t){var r=e[ft]();if(C(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Ki(e){return new F(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?A(function(o,i){return e(o,i,n)}):de,ge(1),r?He(t):Vn(function(){return new Zt}))}}function zn(){for(var e=[],t=0;t=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new x}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,s=i===void 0?!0:i,a=e.resetOnRefCountZero,c=a===void 0?!0:a;return function(f){var u,p,m,d=0,h=!1,v=!1,G=function(){p==null||p.unsubscribe(),p=void 0},oe=function(){G(),u=m=void 0,h=v=!1},N=function(){var T=u;oe(),T==null||T.unsubscribe()};return y(function(T,Qe){d++,!v&&!h&&G();var De=m=m!=null?m:r();Qe.add(function(){d--,d===0&&!v&&!h&&(p=$r(N,c))}),De.subscribe(Qe),!u&&d>0&&(u=new rt({next:function($e){return De.next($e)},error:function($e){v=!0,G(),p=$r(oe,o,$e),De.error($e)},complete:function(){h=!0,G(),p=$r(oe,s),De.complete()}}),U(T).subscribe(u))})(f)}}function $r(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function z(e,t=document){let r=ce(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function ce(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),V(e===_e()),B())}function Xe(e){return{x:e.offsetLeft,y:e.offsetTop}}function Qn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,Te),l(()=>Xe(e)),V(Xe(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,Te),l(()=>rr(e)),V(rr(e)))}var Gn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!Dr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),ga?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!Dr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=va.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Bn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Xn=typeof WeakMap!="undefined"?new WeakMap:new Gn,Zn=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=ya.getInstance(),n=new Aa(t,r,this);Xn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){Zn.prototype[e]=function(){var t;return(t=Xn.get(this))[e].apply(t,arguments)}});var Ca=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:Zn}(),eo=Ca;var to=new x,Ra=$(()=>k(new eo(e=>{for(let t of e)to.next(t)}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),J(1));function he(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ye(e){return Ra.pipe(S(t=>t.observe(e)),g(t=>to.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(()=>he(e)))),V(he(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var ro=new x,ka=$(()=>k(new IntersectionObserver(e=>{for(let t of e)ro.next(t)},{threshold:0}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),J(1));function sr(e){return ka.pipe(S(t=>t.observe(e)),g(t=>ro.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function no(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=he(e),o=bt(e);return r>=o.height-n.height-t}),B())}var cr={drawer:z("[data-md-toggle=drawer]"),search:z("[data-md-toggle=search]")};function oo(e){return cr[e].checked}function Ke(e,t){cr[e].checked!==t&&cr[e].click()}function Ue(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),V(t.checked))}function Ha(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Pa(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(V(!1))}function io(){let e=b(window,"keydown").pipe(A(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:oo("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),A(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!Ha(n,r)}return!0}),pe());return Pa().pipe(g(t=>t?_:e))}function le(){return new URL(location.href)}function ot(e){location.href=e.href}function ao(){return new x}function so(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)so(e,r)}function M(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)so(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function co(){return location.hash.substring(1)}function Vr(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function $a(e){return L(b(window,"hashchange"),e).pipe(l(co),V(co()),A(t=>t.length>0),J(1))}function fo(e){return $a(e).pipe(l(t=>ce(`[id="${t}"]`)),A(t=>typeof t!="undefined"))}function zr(e){let t=matchMedia(e);return er(r=>t.addListener(()=>r(t.matches))).pipe(V(t.matches))}function uo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(V(e.matches))}function Nr(e,t){return e.pipe(g(r=>r?t():_))}function ur(e,t={credentials:"same-origin"}){return ue(fetch(`${e}`,t)).pipe(fe(()=>_),g(r=>r.status!==200?Tt(()=>new Error(r.statusText)):k(r)))}function We(e,t){return ur(e,t).pipe(g(r=>r.json()),J(1))}function po(e,t){let r=new DOMParser;return ur(e,t).pipe(g(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),J(1))}function pr(e){let t=M("script",{src:e});return $(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(g(()=>Tt(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),R(()=>document.head.removeChild(t)),ge(1))))}function lo(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function mo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(lo),V(lo()))}function ho(){return{width:innerWidth,height:innerHeight}}function bo(){return b(window,"resize",{passive:!0}).pipe(l(ho),V(ho()))}function vo(){return Q([mo(),bo()]).pipe(l(([e,t])=>({offset:e,size:t})),J(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(Z("size")),o=Q([n,r]).pipe(l(()=>Xe(e)));return Q([r,t,o]).pipe(l(([{height:i},{offset:s,size:a},{x:c,y:f}])=>({offset:{x:s.x-c,y:s.y-f+i},size:a})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(s=>{let a=document.createElement("script");a.src=i,a.onload=s,document.body.appendChild(a)})),Promise.resolve())}var r=class extends EventTarget{constructor(n){super(),this.url=n,this.m=i=>{i.source===this.w&&(this.dispatchEvent(new MessageEvent("message",{data:i.data})),this.onmessage&&this.onmessage(i))},this.e=(i,s,a,c,f)=>{if(s===`${this.url}`){let u=new ErrorEvent("error",{message:i,filename:s,lineno:a,colno:c,error:f});this.dispatchEvent(u),this.onerror&&this.onerror(u)}};let o=document.createElement("iframe");o.hidden=!0,document.body.appendChild(this.iframe=o),this.w.document.open(),this.w.document.write(` + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Documentation

+ +

This section goes over various Documentation for the Infrastructure team. Please +use the menu items to find the various pages of interest.

+

Resources

+ +
+
+
+

URL: https://accounts.rockylinux.org

+

Purpose: Account Services maintains the accounts for almost all components of the Rocky ecosystem

+

Technology: Noggin used by Fedora Infrastructure

+

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

+
+
+

URL: https://git.resf.org

+

Purpose: General projects, code, and so on for the Rocky Enterprise Software Foundation.

+

Technology: Gitea

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://github.com/rocky-linux

+

Purpose: General purpose code, assets, and so on for Rocky Linux. Some content is mirrored to the RESF Git Service.

+

Technology: GitHub

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://git.rockylinux.org

+

Purpose: Packages and light code for the Rocky Linux distribution

+

Technology: GitLab

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://lists.resf.org

+

Purpose: Users can subscribe and interact with various mail lists for the Rocky ecosystem

+

Technology: Mailman 3 + Hyper Kitty

+

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameEmailMattermost NameIRC Name
Neil Hanlonneil@resf.org@neilneil
Taylor Goodwilltg@resf.org@tgotg
Louis Abellabel@rockylinux.org@nazunalikaSokel/label/Sombra
+
+
+
+ +
+
+ + + Last update: + April 12, 2023 + + + +
+ + + + + + +
+
+ + +
+ + + +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guidelines/awx_scm_guidelines/index.html b/guidelines/awx_scm_guidelines/index.html new file mode 100644 index 0000000..73d29b1 --- /dev/null +++ b/guidelines/awx_scm_guidelines/index.html @@ -0,0 +1,867 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + AWX / Ansible SCM Guidelines - Infrastructure Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

AWX / Ansible SCM Guidelines

+ +

This document covers the guidelines as set out by the Infrastructure/Core group for designing modular repositories that may be used in the Rocky AWX instance or local execution based on team needs. This is meant to supersede the guidelines in the ansible-awx-template repository.

+

This does not cover detailed examples, but is meant to get teams and their contributors started in designing or improving upon all ansible related activities for their group.

+

Contact Information

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OwnerInfrastructure Team
Email Contactinfrastructure@rockylinux.org
Mattermost Contacts@label
Mattermost Contacts@neil
Mattermost Contacts@tgo
Mattermost Channels~Infrastructure
+

Guidelines

+

This section covers the basics for your AWX project. It is absolutely important that you start with these as an absolute bare minimum. While you will be forking/cloning off of infrastructure/ansible-awx-template and using that as the starting point, the next few sections will explain the basic structure and basic design principals.

+

You should begin by starting from the Infrastructure Ansible AWX Template.

+

Root Structure

+

The general structure will always start from this:

+
.
+├── somePlaybook.yml
+├── defaults
+│   └── main.yml
+├── files
+├── handlers
+│   └── main.yml
+├── tasks
+│   └── main.yml
+├── templates
+├── tests
+│   ├── inventory
+│   └── test.yml
+└── vars
+    └── main.yml
+
+

This structure follows the basic expected structure for ansible (this means ignoring AWX/Tower). If you are familiar with ansible already, you may already know how these files and directories work at an operational level. The gist of it is:

+
    +
  • All playbooks should be in the root and import tasks from ./tasks if needed
  • +
  • Vars should be clearly defined where needed in vars, defaults, and/or playbooks
  • +
  • Files and templates should be created with a purpose
  • +
  • Handlers should be clearly defined and used
  • +
  • There should be wiggle room to add callback_plugins, filter_plugins, libraries
  • +
+

With these basic ideas in mind, we can move into playbook design.

+

Designing Playbooks

+

Generally, your playbooks should be doing the following:

+
    +
  1. Checking if ansible can be ran on a specific host
  2. +
  3. Asserting if variables are filled and are correctly formed, if applicable
  4. +
  5. Importing tasks from the ./tasks directory
  6. +
  7. Importing roles, if necessary
  8. +
  9. Post tasks, if necessary
  10. +
+

At no point should you be using ./tasks/main.yml under any circumstance.

+

Pre-flight and Post-flight Tasks

+

In majority of cases, you will need to have pre-flight and post-flight tasks. These aren't needed in all cases, but they should be used as a starting point.

+
  pre_tasks:
+    - name: Check if ansible cannot be run here
+      ansible.builtin.stat:
+        path: /etc/no-ansible
+      register: no_ansible
+
+    - name: Verify if we can run ansible
+      ansible.builtin.assert:
+        that:
+          - "not no_ansible.stat.exists"
+        success_msg: "We are able to run on this node"
+        fail_msg: "/etc/no-ansible exists - skipping run on this node"
+
+    # Assertions and other checks here
+
+  # Import roles/tasks here
+
+  post_tasks:
+    - name: Touching run file that ansible has ran here
+      ansible.builtin.file:
+        path: /var/log/ansible.run
+        state: touch
+        mode: '0644'
+        owner: root
+        group: root
+
+

Tasks General Information

+

Ensure that your tasks are using FQCN. This means, even for the simple modules such as file, you should be using ansible.builtin.file to be compliant with ansible-lint 6+ and ansible 2.12+.

+

Comments

+

Each playbook should have comments or a name descriptor that explains what the playbook does or how it is used. If not available, README-... can be used in place, especially in the case of adhoc playbooks that take or require input. Documentation for each playbook/role does not have to be on a wiki. Comments or README's should be perfectly sufficient.

+

Tags

+

Ensure that you are using relevant tags where necessary for your tasks. This will allow you or the deployers to have deeper control of what is ran or called in AWX.

+

Playbook Naming System

+

When making playbooks, there is a set of predefined prefixes you will need to set. It is highly discouraged to step outside of these prefixes.

+
init-* -> Starting playbooks that run solo or import other playbooks that start
+          with import-. Can also be used to run updates or repetive tasks that
+          adhoc may not suffice and running a role playbook is too much overhead.
+
+adhoc  -> These playbooks are one-off playbooks that can be used on the CLI or
+          in AWX. These are typically for basic tasks.
+
+import -> Playbooks that should be imported from the top level playbooks or
+          used to "import" or "add" data somewhere (e.g., a database or LDAP)
+
+role-* -> These playbooks call roles for potential tasks or even roles in general.
+
+
+

Using the role prefix without an ansible role

+

It is perfectly fine to use role- as a way to say "this system will do or be X" without calling out to an ansible role. You may use role for this case or you can use init. This is not a strict requirement and you should go with what feels right for your project.

+
+

Defining Hosts

+

There will likely be multiple dynamic inventory sources used for hosts managed by AWX, and as a result, there will be a lot of groups defined with one or more hosts at a time. As this is the case, here are some things to keep in mind:

+
    +
  • Use group names where necessary
  • +
  • Use localhost if you aren't actually doing anything to a system (e.g., you're calling an API) and you don't have to connect to a system to use said API
  • +
  • +

    When filling in the hosts directive, follow these general guidelines:

    +
      +
    • If it applies to all hosts in an inventory, use all
    • +
    • If you want the host or a group of hosts to be selectable (via dropdown or manual input), set host: {{ host }} and the host var can be defined as an extra var
    • +
    • If the above two are not applicable and you must set a hostname, you may do so. Note that this will require you to be more vigilant in keeping your repository up to date.
    • +
    +
  • +
+
Local Inventory Files
+

Generally local inventory files are not recommended. Some general rules to follow is this:

+
    +
  • If your project can be ran in AWX and locally outside of AWX, the inventory file should not be committed as inventory (the current .gitignore prevents this from being committed by default)
  • +
  • If your project is local only (meaning it will not be used in AWX, but your team will be using it locally), you may modify .gitignore to include the file
  • +
+

We want to prevent AWX from picking up a random inventory that isn't defined within it.

+
Local ansible.cfg files
+

General ansible.cfg files are not recommended as they would be picked up during normal operation. These should be provided only for special cases. Optionally, you may provide it under another name that a user can reference for local execution outside of AWX.

+

Collections and Roles

+

Collections and roles should be defined in a requirements.yml in their respective directories. AWX will pick them up. Optionally, you can provide a playbook or script to install roles and collections locally. Example commands that could be in a script or playbook:

+
ansible-galaxy collection install -r collections/requirements.yml
+ansible-galaxy role install -r roles/requirements.yml
+
+

Tools like ansible-navigator and ansible-builder can also help in this area as well.

+

Pre-commits / linting

+

When committing, pre-commit must run to verify your changes. They must be passing to be pushed up. This is an absolute requirement, even for roles. There are very rare exceptions to this rule and they may be granted depending on what it is.

+

When the linter passes, a push can be performed. After that, if a PR is necessary, open one. Otherwise, it should be free to use locally or in AWX.

+

Tests

+

A template generally comes with a tests directory. While not strictly required, it is recommended to create a suite of tests to ensure most, if not all of your playbooks are in working order. This is similar to providing tests to ansible collections, in that they should test at least basic functionality.

+

Complex situations can be tested for as well and is encouraged.

+ +
+
+ + + Last update: + April 13, 2023 + + + +
+ + + + + + +
+
+ + +
+ + + +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guidelines/index.html b/guidelines/index.html new file mode 100644 index 0000000..a726651 --- /dev/null +++ b/guidelines/index.html @@ -0,0 +1,610 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Guidelines - Infrastructure Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Guidelines

+ +

This section goes over guidelines that the Infrastructure team has set out for +anything related to the infrastructure managed for the RESF and Rocky Linux.

+

All guidelines are listed on the left side of this page.

+

Resources

+ +
+
+
+

URL: https://accounts.rockylinux.org

+

Purpose: Account Services maintains the accounts for almost all components of the Rocky ecosystem

+

Technology: Noggin used by Fedora Infrastructure

+

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

+
+
+

URL: https://git.resf.org

+

Purpose: General projects, code, and so on for the Rocky Enterprise Software Foundation.

+

Technology: Gitea

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://github.com/rocky-linux

+

Purpose: General purpose code, assets, and so on for Rocky Linux. Some content is mirrored to the RESF Git Service.

+

Technology: GitHub

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://git.rockylinux.org

+

Purpose: Packages and light code for the Rocky Linux distribution

+

Technology: GitLab

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://lists.resf.org

+

Purpose: Users can subscribe and interact with various mail lists for the Rocky ecosystem

+

Technology: Mailman 3 + Hyper Kitty

+

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameEmailMattermost NameIRC Name
Neil Hanlonneil@resf.org@neilneil
Taylor Goodwilltg@resf.org@tgotg
Louis Abellabel@rockylinux.org@nazunalikaSokel/label/Sombra
+
+
+
+ +
+
+ + + Last update: + April 12, 2023 + + + +
+ + + + + + +
+
+ + +
+ + + +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/include/resources_bottom/index.html b/include/resources_bottom/index.html new file mode 100644 index 0000000..b555b98 --- /dev/null +++ b/include/resources_bottom/index.html @@ -0,0 +1,607 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Resources bottom - Infrastructure Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Resources bottom

+ +

Resources

+ +
+
+
+

URL: https://accounts.rockylinux.org

+

Purpose: Account Services maintains the accounts for almost all components of the Rocky ecosystem

+

Technology: Noggin used by Fedora Infrastructure

+

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

+
+
+

URL: https://git.resf.org

+

Purpose: General projects, code, and so on for the Rocky Enterprise Software Foundation.

+

Technology: Gitea

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://github.com/rocky-linux

+

Purpose: General purpose code, assets, and so on for Rocky Linux. Some content is mirrored to the RESF Git Service.

+

Technology: GitHub

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://git.rockylinux.org

+

Purpose: Packages and light code for the Rocky Linux distribution

+

Technology: GitLab

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://lists.resf.org

+

Purpose: Users can subscribe and interact with various mail lists for the Rocky ecosystem

+

Technology: Mailman 3 + Hyper Kitty

+

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameEmailMattermost NameIRC Name
Neil Hanlonneil@resf.org@neilneil
Taylor Goodwilltg@resf.org@tgotg
Louis Abellabel@rockylinux.org@nazunalikaSokel/label/Sombra
+
+
+
+ +
+
+ + + Last update: + April 11, 2023 + + + +
+ + + + + + +
+
+ + +
+ + + +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..d5e6963 --- /dev/null +++ b/index.html @@ -0,0 +1,655 @@ + + + + + + + + + + + + + + + + + + + + + + + + Infrastructure Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Infrastructure Wiki

+ +

Responsibilities

+

Meetings / Communications

+

Members

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RoleNameEmailMattermost NameIRC Name
Infrastructure LeadNeil Hanlonneil@resf.org@neilneil
Infrastructure LeadTaylor Goodwilltg@resf.org@tgotg
Infrastructure, IdM & Release EngineeringLouis Abellabel@rockylinux.org@nazunalikaSokel/label/Sombra
InfrastructureRandolph@meltroN/A
InfrastructurePatrick Roberts@preachermanxN/A
+ +
+
+ + + Last update: + April 11, 2023 + + + +
+ + + + + + +
+
+ + +
+ + + +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..ce079b8 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Infrastructure Wiki","text":""},{"location":"#links","title":"Links","text":""},{"location":"#responsibilities","title":"Responsibilities","text":""},{"location":"#meetings-communications","title":"Meetings / Communications","text":""},{"location":"#members","title":"Members","text":"Role Name Email Mattermost Name IRC Name Infrastructure Lead Neil Hanlon neil@resf.org @neil neil Infrastructure Lead Taylor Goodwill tg@resf.org @tgo tg Infrastructure, IdM & Release Engineering Louis Abel label@rockylinux.org @nazunalika Sokel/label/Sombra Infrastructure Randolph @meltro N/A Infrastructure Patrick Roberts @preachermanx N/A"},{"location":"documentation/","title":"Documentation","text":"

This section goes over various Documentation for the Infrastructure team. Please use the menu items to find the various pages of interest.

Resources Account ServicesGit (RESF Git Service)Git (Rocky Linux GitHub)Git (Rocky Linux GitLab)Mail ListsContacts

URL: https://accounts.rockylinux.org

Purpose: Account Services maintains the accounts for almost all components of the Rocky ecosystem

Technology: Noggin used by Fedora Infrastructure

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

URL: https://git.resf.org

Purpose: General projects, code, and so on for the Rocky Enterprise Software Foundation.

Technology: Gitea

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://github.com/rocky-linux

Purpose: General purpose code, assets, and so on for Rocky Linux. Some content is mirrored to the RESF Git Service.

Technology: GitHub

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://git.rockylinux.org

Purpose: Packages and light code for the Rocky Linux distribution

Technology: GitLab

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://lists.resf.org

Purpose: Users can subscribe and interact with various mail lists for the Rocky ecosystem

Technology: Mailman 3 + Hyper Kitty

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

Name Email Mattermost Name IRC Name Neil Hanlon neil@resf.org @neil neil Taylor Goodwill tg@resf.org @tgo tg Louis Abel label@rockylinux.org @nazunalika Sokel/label/Sombra"},{"location":"guidelines/","title":"Guidelines","text":"

This section goes over guidelines that the Infrastructure team has set out for anything related to the infrastructure managed for the RESF and Rocky Linux.

All guidelines are listed on the left side of this page.

Resources Account ServicesGit (RESF Git Service)Git (Rocky Linux GitHub)Git (Rocky Linux GitLab)Mail ListsContacts

URL: https://accounts.rockylinux.org

Purpose: Account Services maintains the accounts for almost all components of the Rocky ecosystem

Technology: Noggin used by Fedora Infrastructure

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

URL: https://git.resf.org

Purpose: General projects, code, and so on for the Rocky Enterprise Software Foundation.

Technology: Gitea

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://github.com/rocky-linux

Purpose: General purpose code, assets, and so on for Rocky Linux. Some content is mirrored to the RESF Git Service.

Technology: GitHub

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://git.rockylinux.org

Purpose: Packages and light code for the Rocky Linux distribution

Technology: GitLab

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://lists.resf.org

Purpose: Users can subscribe and interact with various mail lists for the Rocky ecosystem

Technology: Mailman 3 + Hyper Kitty

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

Name Email Mattermost Name IRC Name Neil Hanlon neil@resf.org @neil neil Taylor Goodwill tg@resf.org @tgo tg Louis Abel label@rockylinux.org @nazunalika Sokel/label/Sombra"},{"location":"guidelines/awx_scm_guidelines/","title":"AWX / Ansible SCM Guidelines","text":"

This document covers the guidelines as set out by the Infrastructure/Core group for designing modular repositories that may be used in the Rocky AWX instance or local execution based on team needs. This is meant to supersede the guidelines in the ansible-awx-template repository.

This does not cover detailed examples, but is meant to get teams and their contributors started in designing or improving upon all ansible related activities for their group.

"},{"location":"guidelines/awx_scm_guidelines/#contact-information","title":"Contact Information","text":"Owner Infrastructure Team Email Contact infrastructure@rockylinux.org Mattermost Contacts @label Mattermost Contacts @neil Mattermost Contacts @tgo Mattermost Channels ~Infrastructure"},{"location":"guidelines/awx_scm_guidelines/#guidelines","title":"Guidelines","text":"

This section covers the basics for your AWX project. It is absolutely important that you start with these as an absolute bare minimum. While you will be forking/cloning off of infrastructure/ansible-awx-template and using that as the starting point, the next few sections will explain the basic structure and basic design principals.

You should begin by starting from the Infrastructure Ansible AWX Template.

"},{"location":"guidelines/awx_scm_guidelines/#root-structure","title":"Root Structure","text":"

The general structure will always start from this:

.\n\u251c\u2500\u2500 somePlaybook.yml\n\u251c\u2500\u2500 defaults\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 main.yml\n\u251c\u2500\u2500 files\n\u251c\u2500\u2500 handlers\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 main.yml\n\u251c\u2500\u2500 tasks\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 main.yml\n\u251c\u2500\u2500 templates\n\u251c\u2500\u2500 tests\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 inventory\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 test.yml\n\u2514\u2500\u2500 vars\n    \u2514\u2500\u2500 main.yml\n

This structure follows the basic expected structure for ansible (this means ignoring AWX/Tower). If you are familiar with ansible already, you may already know how these files and directories work at an operational level. The gist of it is:

  • All playbooks should be in the root and import tasks from ./tasks if needed
  • Vars should be clearly defined where needed in vars, defaults, and/or playbooks
  • Files and templates should be created with a purpose
  • Handlers should be clearly defined and used
  • There should be wiggle room to add callback_plugins, filter_plugins, libraries

With these basic ideas in mind, we can move into playbook design.

"},{"location":"guidelines/awx_scm_guidelines/#designing-playbooks","title":"Designing Playbooks","text":"

Generally, your playbooks should be doing the following:

  1. Checking if ansible can be ran on a specific host
  2. Asserting if variables are filled and are correctly formed, if applicable
  3. Importing tasks from the ./tasks directory
  4. Importing roles, if necessary
  5. Post tasks, if necessary

At no point should you be using ./tasks/main.yml under any circumstance.

"},{"location":"guidelines/awx_scm_guidelines/#pre-flight-and-post-flight-tasks","title":"Pre-flight and Post-flight Tasks","text":"

In majority of cases, you will need to have pre-flight and post-flight tasks. These aren't needed in all cases, but they should be used as a starting point.

  pre_tasks:\n    - name: Check if ansible cannot be run here\n      ansible.builtin.stat:\n        path: /etc/no-ansible\n      register: no_ansible\n\n    - name: Verify if we can run ansible\n      ansible.builtin.assert:\n        that:\n          - \"not no_ansible.stat.exists\"\n        success_msg: \"We are able to run on this node\"\n        fail_msg: \"/etc/no-ansible exists - skipping run on this node\"\n\n    # Assertions and other checks here\n\n  # Import roles/tasks here\n\n  post_tasks:\n    - name: Touching run file that ansible has ran here\n      ansible.builtin.file:\n        path: /var/log/ansible.run\n        state: touch\n        mode: '0644'\n        owner: root\n        group: root\n
"},{"location":"guidelines/awx_scm_guidelines/#tasks-general-information","title":"Tasks General Information","text":"

Ensure that your tasks are using FQCN. This means, even for the simple modules such as file, you should be using ansible.builtin.file to be compliant with ansible-lint 6+ and ansible 2.12+.

"},{"location":"guidelines/awx_scm_guidelines/#comments","title":"Comments","text":"

Each playbook should have comments or a name descriptor that explains what the playbook does or how it is used. If not available, README-... can be used in place, especially in the case of adhoc playbooks that take or require input. Documentation for each playbook/role does not have to be on a wiki. Comments or README's should be perfectly sufficient.

"},{"location":"guidelines/awx_scm_guidelines/#tags","title":"Tags","text":"

Ensure that you are using relevant tags where necessary for your tasks. This will allow you or the deployers to have deeper control of what is ran or called in AWX.

"},{"location":"guidelines/awx_scm_guidelines/#playbook-naming-system","title":"Playbook Naming System","text":"

When making playbooks, there is a set of predefined prefixes you will need to set. It is highly discouraged to step outside of these prefixes.

init-* -> Starting playbooks that run solo or import other playbooks that start\n          with import-. Can also be used to run updates or repetive tasks that\n          adhoc may not suffice and running a role playbook is too much overhead.\n\nadhoc  -> These playbooks are one-off playbooks that can be used on the CLI or\n          in AWX. These are typically for basic tasks.\n\nimport -> Playbooks that should be imported from the top level playbooks or\n          used to \"import\" or \"add\" data somewhere (e.g., a database or LDAP)\n\nrole-* -> These playbooks call roles for potential tasks or even roles in general.\n

Using the role prefix without an ansible role

It is perfectly fine to use role- as a way to say \"this system will do or be X\" without calling out to an ansible role. You may use role for this case or you can use init. This is not a strict requirement and you should go with what feels right for your project.

"},{"location":"guidelines/awx_scm_guidelines/#defining-hosts","title":"Defining Hosts","text":"

There will likely be multiple dynamic inventory sources used for hosts managed by AWX, and as a result, there will be a lot of groups defined with one or more hosts at a time. As this is the case, here are some things to keep in mind:

  • Use group names where necessary
  • Use localhost if you aren't actually doing anything to a system (e.g., you're calling an API) and you don't have to connect to a system to use said API
  • When filling in the hosts directive, follow these general guidelines:

    • If it applies to all hosts in an inventory, use all
    • If you want the host or a group of hosts to be selectable (via dropdown or manual input), set host: {{ host }} and the host var can be defined as an extra var
    • If the above two are not applicable and you must set a hostname, you may do so. Note that this will require you to be more vigilant in keeping your repository up to date.
"},{"location":"guidelines/awx_scm_guidelines/#local-inventory-files","title":"Local Inventory Files","text":"

Generally local inventory files are not recommended. Some general rules to follow is this:

  • If your project can be ran in AWX and locally outside of AWX, the inventory file should not be committed as inventory (the current .gitignore prevents this from being committed by default)
  • If your project is local only (meaning it will not be used in AWX, but your team will be using it locally), you may modify .gitignore to include the file

We want to prevent AWX from picking up a random inventory that isn't defined within it.

"},{"location":"guidelines/awx_scm_guidelines/#local-ansiblecfg-files","title":"Local ansible.cfg files","text":"

General ansible.cfg files are not recommended as they would be picked up during normal operation. These should be provided only for special cases. Optionally, you may provide it under another name that a user can reference for local execution outside of AWX.

"},{"location":"guidelines/awx_scm_guidelines/#collections-and-roles","title":"Collections and Roles","text":"

Collections and roles should be defined in a requirements.yml in their respective directories. AWX will pick them up. Optionally, you can provide a playbook or script to install roles and collections locally. Example commands that could be in a script or playbook:

ansible-galaxy collection install -r collections/requirements.yml\nansible-galaxy role install -r roles/requirements.yml\n

Tools like ansible-navigator and ansible-builder can also help in this area as well.

"},{"location":"guidelines/awx_scm_guidelines/#pre-commits-linting","title":"Pre-commits / linting","text":"

When committing, pre-commit must run to verify your changes. They must be passing to be pushed up. This is an absolute requirement, even for roles. There are very rare exceptions to this rule and they may be granted depending on what it is.

When the linter passes, a push can be performed. After that, if a PR is necessary, open one. Otherwise, it should be free to use locally or in AWX.

"},{"location":"guidelines/awx_scm_guidelines/#tests","title":"Tests","text":"

A template generally comes with a tests directory. While not strictly required, it is recommended to create a suite of tests to ensure most, if not all of your playbooks are in working order. This is similar to providing tests to ansible collections, in that they should test at least basic functionality.

Complex situations can be tested for as well and is encouraged.

"},{"location":"include/resources_bottom/","title":"Resources bottom","text":"Resources Account ServicesGit (RESF Git Service)Git (Rocky Linux GitHub)Git (Rocky Linux GitLab)Mail ListsContacts

URL: https://accounts.rockylinux.org

Purpose: Account Services maintains the accounts for almost all components of the Rocky ecosystem

Technology: Noggin used by Fedora Infrastructure

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

URL: https://git.resf.org

Purpose: General projects, code, and so on for the Rocky Enterprise Software Foundation.

Technology: Gitea

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://github.com/rocky-linux

Purpose: General purpose code, assets, and so on for Rocky Linux. Some content is mirrored to the RESF Git Service.

Technology: GitHub

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://git.rockylinux.org

Purpose: Packages and light code for the Rocky Linux distribution

Technology: GitLab

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://lists.resf.org

Purpose: Users can subscribe and interact with various mail lists for the Rocky ecosystem

Technology: Mailman 3 + Hyper Kitty

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

Name Email Mattermost Name IRC Name Neil Hanlon neil@resf.org @neil neil Taylor Goodwill tg@resf.org @tgo tg Louis Abel label@rockylinux.org @nazunalika Sokel/label/Sombra"},{"location":"sop/","title":"SOP (Standard Operationg Procedures)","text":"

This section goes over the various SOP's for the Infrastructure Team. Please use the menu items to find the various pages of interest.

Resources Account ServicesGit (RESF Git Service)Git (Rocky Linux GitHub)Git (Rocky Linux GitLab)Mail ListsContacts

URL: https://accounts.rockylinux.org

Purpose: Account Services maintains the accounts for almost all components of the Rocky ecosystem

Technology: Noggin used by Fedora Infrastructure

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

URL: https://git.resf.org

Purpose: General projects, code, and so on for the Rocky Enterprise Software Foundation.

Technology: Gitea

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://github.com/rocky-linux

Purpose: General purpose code, assets, and so on for Rocky Linux. Some content is mirrored to the RESF Git Service.

Technology: GitHub

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://git.rockylinux.org

Purpose: Packages and light code for the Rocky Linux distribution

Technology: GitLab

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

URL: https://lists.resf.org

Purpose: Users can subscribe and interact with various mail lists for the Rocky ecosystem

Technology: Mailman 3 + Hyper Kitty

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

Name Email Mattermost Name IRC Name Neil Hanlon neil@resf.org @neil neil Taylor Goodwill tg@resf.org @tgo tg Louis Abel label@rockylinux.org @nazunalika Sokel/label/Sombra"},{"location":"sop/idm_sop_gdpr/","title":"SOP: Personal Data Request - Deletion","text":"

This SOP covers how the Rocky Enterprise Software Foundation (RESF) and Rocky Linux Infrastructure Team handles GDRP (General Data Protection Regulation) data delete requests. It contains information about how System Administrators will use Ansible and other tooling to respond to delete requests.

"},{"location":"sop/idm_sop_gdpr/#contact-information","title":"Contact Information","text":"Owner Infrastructure Team & Identity Management Team Email Contact infrastructure@rockylinux.org Email Contact identitymanagement@rockylinux.org Mattermost Contacts @label Mattermost Channels ~Infrastructure"},{"location":"sop/idm_sop_gdpr/#responding-to-a-deletion-request","title":"Responding to a Deletion Request","text":"

This section covers how a system administrator will use our adhoc-ipauser-disable-pdr.yml playbook to respond to a delete request.

If a request has been received via email, perform the following steps:

  1. If request was received by email: Open a ticket at the bug tracker under the Account Services product (Click the drop down in the top right corner, click \"Account Services\", select \"Report Issue\")

    • Set category to Account Requests - Personal Data Request
    • Assign to yourself if possible
    • Summary should be set: PDR - Email Delete Request for <USER/EMAIL>
    • Description should be set to the snippet PDR Request - Remove Personal Information or copied directly from the email if the template was followed.
    • Use the ID for the ansible playbook
  2. On the ansible host, run the necessary ansible playbook: ansible-playbook -i inventories/production/hosts.ini playbooks/adhoc-ipauser-disable-pdr.yml --extra-vars='ipa_user=<USER> ticket_id=BT<TICKET>'

  3. Leave a comment on the issue that the disable request was performed.
  4. Email the affected user:

Hello. We have reviewed your account request and have performed the requested\nchanges. The ticket <ID> has been closed and set to private.\n\nPlease note that some public content such as mailing lists cannot be deleted\nsince some information is meant to serve the RESF legitimate business\ninterests, the public interest, and the interest of the open source community.\n\nThank you, please let us know if you have any further questions.\n
4. Set ticket to RESOLVED

"},{"location":"sop/idm_sop_mm_ras/","title":"SOP: Mattermost and RAS Group Sync","text":"

This SOP covers how the Rocky Enterprise Software Foundation (RESF) and Rocky Linux Infrastructure handles group syncing between the Rocky Account Services and Mattermost Channels. It contains information about how System Administrators will create groups, the templates, and how to setup syncing within Mattermost.

Note: This assumes the user is logging in with their RAS credentials to Mattermost.

"},{"location":"sop/idm_sop_mm_ras/#contact-information","title":"Contact Information","text":"Owner Infrastructure Team & Identity Management Team Email Contact infrastructure@rockylinux.org Email Contact identitymanagement@rockylinux.org Mattermost Contacts @label Mattermost Contacts @neil Mattermost Channels ~Infrastructure"},{"location":"sop/idm_sop_mm_ras/#creating-the-necessary-group","title":"Creating the necessary group","text":"

This section covers how a system administrator will create a group Rocky Account Services using ansible. The playbook utilized will be adhoc-ipagroup.yml.

  1. First, determine where and how the group will be utilized. The starting template will be mm_X_name. mm is for mattermost, X will be for the designated part of Mattermost (e.g., resf, rl, and so on), and name will be the name of the group in question.
  2. On the ansible host, run the necessary ansible playbook: ansible-playbook -i inventories/production/hosts.ini ansible-ipa-management/adhoc-ipagroup.yml --extra-vars='ipa_group=<GROUP> ipa_description=\"<DESC>\" ipa_nonposix=false ipa_fas=true ipa_group_manager_user=<OWNER>'

    • Ensure that the description is set in a way that it explains what it is for
    • It is unlikely the group will need to have a GID assigned. Assigning the group as nonposix should be sufficient.
    • Setting the group with ipa_fas=true ensures that the group will appear in Rocky Account Services and can be managed there.
    • Setting ipa_group_manager_user will set a user in RAS that can manage the group without requesting for an administrator to do so.
"},{"location":"sop/idm_sop_mm_ras/#syncing-in-mattermost","title":"Syncing in Mattermost","text":"

Within mattermost's administration console, apply the group to the channel as necessary.

"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..12329dc --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,43 @@ + + + + https://infra.rocky.page/ + 2023-04-13 + daily + + + https://infra.rocky.page/documentation/ + 2023-04-13 + daily + + + https://infra.rocky.page/guidelines/ + 2023-04-13 + daily + + + https://infra.rocky.page/guidelines/awx_scm_guidelines/ + 2023-04-13 + daily + + + https://infra.rocky.page/include/resources_bottom/ + 2023-04-13 + daily + + + https://infra.rocky.page/sop/ + 2023-04-13 + daily + + + https://infra.rocky.page/sop/idm_sop_gdpr/ + 2023-04-13 + daily + + + https://infra.rocky.page/sop/idm_sop_mm_ras/ + 2023-04-13 + daily + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000..d376f66 Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/sop/idm_sop_gdpr/index.html b/sop/idm_sop_gdpr/index.html new file mode 100644 index 0000000..f7a33bb --- /dev/null +++ b/sop/idm_sop_gdpr/index.html @@ -0,0 +1,650 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + SOP: Personal Data Request - Deletion - Infrastructure Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

SOP: Personal Data Request - Deletion

+ +

This SOP covers how the Rocky Enterprise Software Foundation (RESF) and Rocky Linux Infrastructure Team handles GDRP (General Data Protection Regulation) data delete requests. It contains information about how System Administrators will use Ansible and other tooling to respond to delete requests.

+

Contact Information

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OwnerInfrastructure Team & Identity Management Team
Email Contactinfrastructure@rockylinux.org
Email Contactidentitymanagement@rockylinux.org
Mattermost Contacts@label
Mattermost Channels~Infrastructure
+

Responding to a Deletion Request

+

This section covers how a system administrator will use our adhoc-ipauser-disable-pdr.yml playbook to respond to a delete request.

+

If a request has been received via email, perform the following steps:

+
    +
  1. +

    If request was received by email: Open a ticket at the bug tracker under the Account Services product (Click the drop down in the top right corner, click "Account Services", select "Report Issue")

    +
      +
    • Set category to Account Requests - Personal Data Request
    • +
    • Assign to yourself if possible
    • +
    • Summary should be set: PDR - Email Delete Request for <USER/EMAIL>
    • +
    • Description should be set to the snippet PDR Request - Remove Personal Information or copied directly from the email if the template was followed.
    • +
    • Use the ID for the ansible playbook
    • +
    +
  2. +
  3. +

    On the ansible host, run the necessary ansible playbook: ansible-playbook -i inventories/production/hosts.ini playbooks/adhoc-ipauser-disable-pdr.yml --extra-vars='ipa_user=<USER> ticket_id=BT<TICKET>'

    +
  4. +
  5. Leave a comment on the issue that the disable request was performed.
  6. +
  7. Email the affected user:
  8. +
+

Hello. We have reviewed your account request and have performed the requested
+changes. The ticket <ID> has been closed and set to private.
+
+Please note that some public content such as mailing lists cannot be deleted
+since some information is meant to serve the RESF legitimate business
+interests, the public interest, and the interest of the open source community.
+
+Thank you, please let us know if you have any further questions.
+
+4. Set ticket to RESOLVED

+ +
+
+ + + Last update: + April 11, 2023 + + + +
+ + + + + + +
+
+ + +
+ + + +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/sop/idm_sop_mm_ras/index.html b/sop/idm_sop_mm_ras/index.html new file mode 100644 index 0000000..c5f2634 --- /dev/null +++ b/sop/idm_sop_mm_ras/index.html @@ -0,0 +1,646 @@ + + + + + + + + + + + + + + + + + + + + + + + + SOP: Mattermost and RAS Group Sync - Infrastructure Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

SOP: Mattermost and RAS Group Sync

+ +

This SOP covers how the Rocky Enterprise Software Foundation (RESF) and Rocky Linux Infrastructure handles group syncing between the Rocky Account Services and Mattermost Channels. It contains information about how System Administrators will create groups, the templates, and how to setup syncing within Mattermost.

+

Note: This assumes the user is logging in with their RAS credentials to Mattermost.

+

Contact Information

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OwnerInfrastructure Team & Identity Management Team
Email Contactinfrastructure@rockylinux.org
Email Contactidentitymanagement@rockylinux.org
Mattermost Contacts@label
Mattermost Contacts@neil
Mattermost Channels~Infrastructure
+

Creating the necessary group

+

This section covers how a system administrator will create a group Rocky Account Services using ansible. The playbook utilized will be adhoc-ipagroup.yml.

+
    +
  1. First, determine where and how the group will be utilized. The starting template will be mm_X_name. mm is for mattermost, X will be for the designated part of Mattermost (e.g., resf, rl, and so on), and name will be the name of the group in question.
  2. +
  3. +

    On the ansible host, run the necessary ansible playbook: ansible-playbook -i inventories/production/hosts.ini ansible-ipa-management/adhoc-ipagroup.yml --extra-vars='ipa_group=<GROUP> ipa_description="<DESC>" ipa_nonposix=false ipa_fas=true ipa_group_manager_user=<OWNER>'

    +
      +
    • Ensure that the description is set in a way that it explains what it is for
    • +
    • It is unlikely the group will need to have a GID assigned. Assigning the group as nonposix should be sufficient.
    • +
    • Setting the group with ipa_fas=true ensures that the group will appear in Rocky Account Services and can be managed there.
    • +
    • Setting ipa_group_manager_user will set a user in RAS that can manage the group without requesting for an administrator to do so.
    • +
    +
  4. +
+

Syncing in Mattermost

+

Within mattermost's administration console, apply the group to the channel as necessary.

+ +
+
+ + + Last update: + April 11, 2023 + + + +
+ + + + + + +
+
+ + +
+ + + +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/sop/index.html b/sop/index.html new file mode 100644 index 0000000..9095001 --- /dev/null +++ b/sop/index.html @@ -0,0 +1,609 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + SOP (Standard Operationg Procedures) - Infrastructure Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

SOP (Standard Operationg Procedures)

+ +

This section goes over the various SOP's for the Infrastructure Team. Please use the menu items +to find the various pages of interest.

+

Resources

+ +
+
+
+

URL: https://accounts.rockylinux.org

+

Purpose: Account Services maintains the accounts for almost all components of the Rocky ecosystem

+

Technology: Noggin used by Fedora Infrastructure

+

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

+
+
+

URL: https://git.resf.org

+

Purpose: General projects, code, and so on for the Rocky Enterprise Software Foundation.

+

Technology: Gitea

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://github.com/rocky-linux

+

Purpose: General purpose code, assets, and so on for Rocky Linux. Some content is mirrored to the RESF Git Service.

+

Technology: GitHub

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://git.rockylinux.org

+

Purpose: Packages and light code for the Rocky Linux distribution

+

Technology: GitLab

+

Contact: ~Infrastructure, ~Development in Mattermost and #rockylinux-infra, #rockylinux-devel in Libera IRC

+
+
+

URL: https://lists.resf.org

+

Purpose: Users can subscribe and interact with various mail lists for the Rocky ecosystem

+

Technology: Mailman 3 + Hyper Kitty

+

Contact: ~Infrastructure in Mattermost and #rockylinux-infra in Libera IRC

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameEmailMattermost NameIRC Name
Neil Hanlonneil@resf.org@neilneil
Taylor Goodwilltg@resf.org@tgotg
Louis Abellabel@rockylinux.org@nazunalikaSokel/label/Sombra
+
+
+
+ +
+
+ + + Last update: + April 11, 2023 + + + +
+ + + + + + +
+
+ + +
+ + + +
+ +
+ + +
+ +
+
+
+
+ + + + + + + + + \ No newline at end of file