diff options
author | Alex Legler <a3li@gentoo.org> | 2012-02-28 02:03:25 +0100 |
---|---|---|
committer | Alex Legler <a3li@gentoo.org> | 2012-02-28 02:03:25 +0100 |
commit | 0c9fbb16e6d3c0eea805958aad4f0b7f35b0e4ce (patch) | |
tree | 19d87887fd10d64053f7f53233f85169ab18d835 | |
download | infra-status-0c9fbb16e6d3c0eea805958aad4f0b7f35b0e4ce.tar.gz infra-status-0c9fbb16e6d3c0eea805958aad4f0b7f35b0e4ce.tar.bz2 infra-status-0c9fbb16e6d3c0eea805958aad4f0b7f35b0e4ce.zip |
Initial commit
27 files changed, 1744 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c019529 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +tmp +output @@ -0,0 +1,80 @@ +#!/usr/bin/env ruby + +# A few helpful tips about the Rules file: +# +# * The string given to #compile and #route are matching patterns for +# identifiers--not for paths. Therefore, you can’t match on extension. +# +# * The order of rules is important: for each item, only the first matching +# rule is applied. +# +# * Item identifiers start and end with a slash (e.g. “/about/” for the file +# “content/about.html”). To select all children, grandchildren, … of an +# item, use the pattern “/about/*/”; “/about/*” will also select the parent, +# because “*” matches zero or more characters. + +compile '/css/*/' do + # don’t filter or layout +end + +compile '/js/*/' do + # don’t filter or layout +end + +compile '/atom' do + filter :erb +end + +compile '*' do + ext = item[:extension].nil? ? nil : item[:extension].split('.').last + + if item.binary? + # don’t filter binary items + elsif ext == 'md' || ext == 'markdown' + filter :erb + filter :rdiscount + + if item[:kind] == 'article' + layout '_post' + snapshot :single_post + end + + layout 'default' + elsif ext == 'haml' + filter :haml + layout 'default' + else + filter :erb + layout 'default' + end +end + +route '/css/*/' do + item.identifier.chop + '.css' +end + +route '/js/*/' do + item.identifier.chop + '.js' +end + +route '/atom' do + item.identifier.chop + '.xml' +end + +route '/notices/*' do + item.identifier.chop + '.html' +end + +route '*' do + if item.binary? + # Write item with identifier /foo/ to /foo.ext + item.identifier.chop + '.' + item[:extension] + else + # Write item with identifier /foo/ to /foo/index.html + item.identifier + 'index.html' + end +end + +layout '*', :haml + +# vim: et sw=2 ts=2: diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..18d2280 --- /dev/null +++ b/config.yaml @@ -0,0 +1,79 @@ +base_url: http://infra-status.gentoo.org + +# A list of file extensions that nanoc will consider to be textual rather than +# binary. If an item with an extension not in this list is found, the file +# will be considered as binary. +text_extensions: [ 'css', 'erb', 'haml', 'htm', 'html', 'js', 'less', 'markdown', 'md', 'php', 'rb', 'sass', 'scss', 'txt', 'xhtml', 'xml', 'coffee' ] + +# The path to the directory where all generated files will be written to. This +# can be an absolute path starting with a slash, but it can also be path +# relative to the site directory. +output_dir: output + +# A list of index filenames, i.e. names of files that will be served by a web +# server when a directory is requested. Usually, index files are named +# “index.html”, but depending on the web server, this may be something else, +# such as “default.htm”. This list is used by nanoc to generate pretty URLs. +index_filenames: [ 'index.html' ] + +# Whether or not to generate a diff of the compiled content when compiling a +# site. The diff will contain the differences between the compiled content +# before and after the last site compilation. +enable_output_diff: false + +prune: + # Whether to automatically remove files not managed by nanoc from the output + # directory. For safety reasons, this is turned off by default. + auto_prune: false + + # Which files and directories you want to exclude from pruning. If you version + # your output directory, you should probably exclude VCS directories such as + # .git, .svn etc. + exclude: [ '.git', '.hg', '.svn', 'CVS' ] + +# The data sources where nanoc loads its data from. This is an array of +# hashes; each array element represents a single data source. By default, +# there is only a single data source that reads data from the “content/” and +# “layout/” directories in the site directory. +data_sources: + - + # The type is the identifier of the data source. By default, this will be + # `filesystem_unified`. + type: filesystem_unified + + # The path where items should be mounted (comparable to mount points in + # Unix-like systems). This is “/” by default, meaning that items will have + # “/” prefixed to their identifiers. If the items root were “/en/” + # instead, an item at content/about.html would have an identifier of + # “/en/about/” instead of just “/about/”. + items_root: / + + # The path where layouts should be mounted. The layouts root behaves the + # same as the items root, but applies to layouts rather than items. + layouts_root: / + + # Whether to allow periods in identifiers. When turned off, everything + # past the first period is considered to be the extension, and when + # turned on, only the characters past the last period are considered to + # be the extension. For example, a file named “content/about.html.erb” + # will have the identifier “/about/” when turned off, but when turned on + # it will become “/about.html/” instead. + allow_periods_in_identifiers: false + +# Configuration for the “watch” command, which watches a site for changes and +# recompiles if necessary. +watcher: + # A list of directories to watch for changes. When editing this, make sure + # that the “output/” and “tmp/” directories are _not_ included in this list, + # because recompiling the site will cause these directories to change, which + # will cause the site to be recompiled, which will cause these directories + # to change, which will cause the site to be recompiled again, and so on. + dirs_to_watch: [ 'content', 'layouts', 'lib' ] + + # A list of single files to watch for changes. As mentioned above, don’t put + # any files from the “output/” or “tmp/” directories in here. + files_to_watch: [ 'config.yaml', 'Rules' ] + + # When to send notifications (using Growl or notify-send). + notify_on_compilation_success: true + notify_on_compilation_failure: true diff --git a/content/atom.xml.erb b/content/atom.xml.erb new file mode 100644 index 0000000..6439efb --- /dev/null +++ b/content/atom.xml.erb @@ -0,0 +1,7 @@ +--- +title: Gentoo Linux Infrastructure Status +author_name: Gentoo Infrastructure Team +author_uri: http://infra-status.gentoo.org/ +is_hidden: true +--- +<%= atom_feed(:content_proc => feed_proc, :articles => feed_articles) %> diff --git a/content/css/1140.css b/content/css/1140.css new file mode 100644 index 0000000..b8d6fa2 --- /dev/null +++ b/content/css/1140.css @@ -0,0 +1,130 @@ +/* CSS Resets */ + +html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,address,cite,code,del,dfn,em,img,ins,q,small,strong,sub,sup,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{border:0;margin:0;padding:0}article,aside,figure,figure img,figcaption,hgroup,footer,header,nav,section,video,object{display:block}a img{border:0}figure{position:relative}figure img{width:100%} + + +/* ==================================================================================================================== */ +/* ! The 1140px Grid V2 by Andy Taylor \ http://cssgrid.net \ http://www.twitter.com/andytlr \ http://www.andytlr.com */ +/* ==================================================================================================================== */ + +.container { +padding-left: 20px; +padding-right: 20px; +} + +.row { +width: 100%; +max-width: 1140px; +min-width: 755px; +margin: 0 auto; +overflow: hidden; +} + +.onecol, .twocol, .threecol, .fourcol, .fivecol, .sixcol, .sevencol, .eightcol, .ninecol, .tencol, .elevencol { +margin-right: 3.8%; +float: left; +min-height: 1px; +} + +.row .onecol { +width: 4.85%; +} + +.row .twocol { +width: 13.45%; +} + +.row .threecol { +width: 22.05%; +} + +.row .fourcol { +width: 30.75%; +} + +.row .fivecol { +width: 39.45%; +} + +.row .sixcol { +width: 48%; +} + +.row .sevencol { +width: 56.75%; +} + +.row .eightcol { +width: 65.4%; +} + +.row .ninecol { +width: 74.05%; +} + +.row .tencol { +width: 82.7%; +} + +.row .elevencol { +width: 91.35%; +} + +.row .twelvecol { +width: 100%; +float: left; +} + +.last { +margin-right: 0px; +} + +img, object, embed { +max-width: 100%; +} + +img { + height: auto; +} + + +/* Smaller screens */ + +@media only screen and (max-width: 1023px) { + + body { + font-size: 0.8em; + line-height: 1.5em; + } + + } + + +/* Mobile */ + +@media handheld, only screen and (max-width: 767px) { + + body { + font-size: 16px; + -webkit-text-size-adjust: none; + } + + .row, body, .container { + width: 100%; + min-width: 0; + margin-left: 0px; + margin-right: 0px; + padding-left: 0px; + padding-right: 0px; + } + + .row .onecol, .row .twocol, .row .threecol, .row .fourcol, .row .fivecol, .row .sixcol, .row .sevencol, .row .eightcol, .row .ninecol, .row .tencol, .row .elevencol, .row .twelvecol { + width: auto; + float: none; + margin-left: 0px; + margin-right: 0px; + padding-left: 20px; + padding-right: 20px; + } + +}
\ No newline at end of file diff --git a/content/css/ie.css b/content/css/ie.css new file mode 100644 index 0000000..530c113 --- /dev/null +++ b/content/css/ie.css @@ -0,0 +1,43 @@ +.onecol { +width: 4.7%; +} + +.twocol { +width: 13.2%; +} + +.threecol { +width: 22.05%; +} + +.fourcol { +width: 30.6%; +} + +.fivecol { +width: 39%; +} + +.sixcol { +width: 48%; +} + +.sevencol { +width: 56.75%; +} + +.eightcol { +width: 61.6%; +} + +.ninecol { +width: 74.05%; +} + +.tencol { +width: 82%; +} + +.elevencol { +width: 91.35%; +}
\ No newline at end of file diff --git a/content/css/screen.css b/content/css/screen.css new file mode 100644 index 0000000..c3970c9 --- /dev/null +++ b/content/css/screen.css @@ -0,0 +1,142 @@ +/* ============================== */ +/* ! Layout for desktop version */ +/* ============================== */ + +body { + font-family: 'Open Sans', sans-serif; + padding-bottom: 3em; +} + +a:link, a:visited { + color: #54487A; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +.right { + float: right; +} + +.header { + background-color: #E8E8E8; + border-top: 2px solid #54487A; + border-bottom: 1px solid #dcdcdc; +} + +.header .row { + padding-top: .25em; + padding-bottom: .25em; +} + +h1 { + font-size: 1.5em; +} + +h2 { + font-size: 1.25em; +} + +h3 { + font-size: 1.1em; + font-weight: 600; +} + +.site-title { + background-color: #f5f5f5; + border-bottom: 1px solid #e8e8e8; + margin-bottom: 1em; +} + +.site-title .row { + padding-top: .25em; + padding-bottom: .25em; +} + +table.statustable { + width: 100%; + border-spacing: 0 2px; +} + +table.statustable td { + padding-bottom: 1px; + border-bottom: 1px solid #e8e8e8; +} + +table.statustable tr.last td { + border: none !important; +} + +table.statustable td.status { + text-align: right; +} + +table.statustable tr.down { + color: #a40000; +} + +table.statustable tr.warning { + color: #ac4a00; +} + +.grey { + background-color: #F5F5F5; +} + +.bottomline { + border-bottom: 1px solid #e8e8e8; + padding-bottom: 1em; + margin-bottom: 1em; +} + +p { + margin-top: .5em; + margin-bottom: .5em; +} + +.post { + margin-top: .5em; + margin-bottom: .5em; + border-top: 1px solid #dcdcdc; +} + +table.dates { + margin-left: 1em; + font-style: italic; +} + +td { + padding-left: 0.25em; + padding-right: 0.25em; +} + +#footer { + border-top: 1px solid #dcdcdc; + position: fixed; + width: 100%; + bottom: 0; + background-color: #E8E8E8; + padding-left: 0; + padding-right: 0; + padding-top: .5em; + padding-bottom: .5em; + font-size: .75em; +} + +/* ============================= */ +/* ! Layout for mobile version */ +/* ============================= */ + +@media handheld, only screen and (max-width: 767px) { + + body { + padding-bottom: 0; + } + + #footer { + position: relative !important; + } + +} diff --git a/content/img/feed.png b/content/img/feed.png Binary files differnew file mode 100644 index 0000000..cdf4e8f --- /dev/null +++ b/content/img/feed.png diff --git a/content/img/information.png b/content/img/information.png Binary files differnew file mode 100644 index 0000000..4ecaf37 --- /dev/null +++ b/content/img/information.png diff --git a/content/img/maintenance.png b/content/img/maintenance.png Binary files differnew file mode 100644 index 0000000..8347aa8 --- /dev/null +++ b/content/img/maintenance.png diff --git a/content/img/na.png b/content/img/na.png Binary files differnew file mode 100644 index 0000000..93807bc --- /dev/null +++ b/content/img/na.png diff --git a/content/img/notice.png b/content/img/notice.png Binary files differnew file mode 100644 index 0000000..adaf4f0 --- /dev/null +++ b/content/img/notice.png diff --git a/content/img/outage.png b/content/img/outage.png Binary files differnew file mode 100644 index 0000000..413291d --- /dev/null +++ b/content/img/outage.png diff --git a/content/img/site_logo.png b/content/img/site_logo.png Binary files differnew file mode 100644 index 0000000..8ff911e --- /dev/null +++ b/content/img/site_logo.png diff --git a/content/img/status_down.png b/content/img/status_down.png Binary files differnew file mode 100644 index 0000000..933272b --- /dev/null +++ b/content/img/status_down.png diff --git a/content/img/status_up.png b/content/img/status_up.png Binary files differnew file mode 100644 index 0000000..3b0e3fc --- /dev/null +++ b/content/img/status_up.png diff --git a/content/img/status_warning.png b/content/img/status_warning.png Binary files differnew file mode 100644 index 0000000..e792fb0 --- /dev/null +++ b/content/img/status_warning.png diff --git a/content/index.haml b/content/index.haml new file mode 100644 index 0000000..129f3e4 --- /dev/null +++ b/content/index.haml @@ -0,0 +1,93 @@ +--- +title: Index +--- +.container.bottomline + .row + .twelvecol.last + %h2 Service Availability Overview + %p + This data is aggregated from our automated service monitoring system as well as the outage and maintenance notices posted below. + .row + .fourcol + %h3 Community Services + %table.statustable + %tr.up + %td gentoo.org Website + %td.status + = service_icons 'www' + %tr + %td Forums + %td.status + = service_icons 'forums' + %tr + %td Wiki + %td.status + = service_icons 'wiki' + %tr + %td Planet Gentoo + %td.status + = service_icons 'planet' + %tr + %td Packages Database + %td.status + = service_icons 'pgo' + %tr + %td Mailing Lists + %td.status + = service_icons 'lists' + %tr.last + %td Mailing List Archives + %td.status + = service_icons 'archives' + .fourcol + %h3 Development Services + %table.statustable + %tr + %td cvs.gentoo.org + %td.status + = service_icons 'cvs' + %tr + %td Bugzilla + %td.status + = service_icons 'bugzilla' + %tr + %td Devmanual + %td.status + = service_icons 'devmanual' + %tr + %td Overlays + %td.status + = service_icons 'overlays' + %tr + %td tinderbox.dev.gentoo.org + %td.status + = service_icons 'tinderbox' + %tr.last + %td sources.gentoo.org + %td.status + = service_icons 'sources' + .fourcol.last + %h3 Developer Resources + %table.statustable + %tr + %td dev.gentoo.org shell access + %td.status + = service_icons 'dgo_ssh' + %tr + %td dev.gentoo.org web hosting + %td.status + = service_icons 'dgo_http' + %tr + %td In-/Outbound Email (SMTP) + %td.status + = service_icons 'dgo_smtp' + %tr.last + %td Mailbox access (POP/IMAP) + %td.status + = service_icons 'dgo_mbox' + +.container + .row + .twelvecol.last + %h2 Maintenance and Outage Notices + = notices diff --git a/content/js/css3-mediaqueries.js b/content/js/css3-mediaqueries.js new file mode 100644 index 0000000..1ea806d --- /dev/null +++ b/content/js/css3-mediaqueries.js @@ -0,0 +1,779 @@ +if(typeof Object.create!=="function"){ +Object.create=function(o){ +function F(){ +}; +F.prototype=o; +return new F(); +}; +} +var ua={toString:function(){ +return navigator.userAgent; +},test:function(s){ +return this.toString().toLowerCase().indexOf(s.toLowerCase())>-1; +}}; +ua.version=(ua.toString().toLowerCase().match(/[\s\S]+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1]; +ua.webkit=ua.test("webkit"); +ua.gecko=ua.test("gecko")&&!ua.webkit; +ua.opera=ua.test("opera"); +ua.ie=ua.test("msie")&&!ua.opera; +ua.ie6=ua.ie&&document.compatMode&&typeof document.documentElement.style.maxHeight==="undefined"; +ua.ie7=ua.ie&&document.documentElement&&typeof document.documentElement.style.maxHeight!=="undefined"&&typeof XDomainRequest==="undefined"; +ua.ie8=ua.ie&&typeof XDomainRequest!=="undefined"; +var domReady=function(){ +var _1=[]; +var _2=function(){ +if(!arguments.callee.done){ +arguments.callee.done=true; +for(var i=0;i<_1.length;i++){ +_1[i](); +} +} +}; +if(document.addEventListener){ +document.addEventListener("DOMContentLoaded",_2,false); +} +if(ua.ie){ +(function(){ +try{ +document.documentElement.doScroll("left"); +} +catch(e){ +setTimeout(arguments.callee,50); +return; +} +_2(); +})(); +document.onreadystatechange=function(){ +if(document.readyState==="complete"){ +document.onreadystatechange=null; +_2(); +} +}; +} +if(ua.webkit&&document.readyState){ +(function(){ +if(document.readyState!=="loading"){ +_2(); +}else{ +setTimeout(arguments.callee,10); +} +})(); +} +window.onload=_2; +return function(fn){ +if(typeof fn==="function"){ +_1[_1.length]=fn; +} +return fn; +}; +}(); +var cssHelper=function(){ +var _3={BLOCKS:/[^\s{][^{]*\{(?:[^{}]*\{[^{}]*\}[^{}]*|[^{}]*)*\}/g,BLOCKS_INSIDE:/[^\s{][^{]*\{[^{}]*\}/g,DECLARATIONS:/[a-zA-Z\-]+[^;]*:[^;]+;/g,RELATIVE_URLS:/url\(['"]?([^\/\)'"][^:\)'"]+)['"]?\)/g,REDUNDANT_COMPONENTS:/(?:\/\*([^*\\\\]|\*(?!\/))+\*\/|@import[^;]+;)/g,REDUNDANT_WHITESPACE:/\s*(,|:|;|\{|\})\s*/g,MORE_WHITESPACE:/\s{2,}/g,FINAL_SEMICOLONS:/;\}/g,NOT_WHITESPACE:/\S+/g}; +var _4,_5=false; +var _6=[]; +var _7=function(fn){ +if(typeof fn==="function"){ +_6[_6.length]=fn; +} +}; +var _8=function(){ +for(var i=0;i<_6.length;i++){ +_6[i](_4); +} +}; +var _9={}; +var _a=function(n,v){ +if(_9[n]){ +var _b=_9[n].listeners; +if(_b){ +for(var i=0;i<_b.length;i++){ +_b[i](v); +} +} +} +}; +var _c=function(_d,_e,_f){ +if(ua.ie&&!window.XMLHttpRequest){ +window.XMLHttpRequest=function(){ +return new ActiveXObject("Microsoft.XMLHTTP"); +}; +} +if(!XMLHttpRequest){ +return ""; +} +var r=new XMLHttpRequest(); +try{ +r.open("get",_d,true); +r.setRequestHeader("X_REQUESTED_WITH","XMLHttpRequest"); +} +catch(e){ +_f(); +return; +} +var _10=false; +setTimeout(function(){ +_10=true; +},5000); +document.documentElement.style.cursor="progress"; +r.onreadystatechange=function(){ +if(r.readyState===4&&!_10){ +if(!r.status&&location.protocol==="file:"||(r.status>=200&&r.status<300)||r.status===304||navigator.userAgent.indexOf("Safari")>-1&&typeof r.status==="undefined"){ +_e(r.responseText); +}else{ +_f(); +} +document.documentElement.style.cursor=""; +r=null; +} +}; +r.send(""); +}; +var _11=function(_12){ +_12=_12.replace(_3.REDUNDANT_COMPONENTS,""); +_12=_12.replace(_3.REDUNDANT_WHITESPACE,"$1"); +_12=_12.replace(_3.MORE_WHITESPACE," "); +_12=_12.replace(_3.FINAL_SEMICOLONS,"}"); +return _12; +}; +var _13={mediaQueryList:function(s){ +var o={}; +var idx=s.indexOf("{"); +var lt=s.substring(0,idx); +s=s.substring(idx+1,s.length-1); +var mqs=[],rs=[]; +var qts=lt.toLowerCase().substring(7).split(","); +for(var i=0;i<qts.length;i++){ +mqs[mqs.length]=_13.mediaQuery(qts[i],o); +} +var rts=s.match(_3.BLOCKS_INSIDE); +if(rts!==null){ +for(i=0;i<rts.length;i++){ +rs[rs.length]=_13.rule(rts[i],o); +} +} +o.getMediaQueries=function(){ +return mqs; +}; +o.getRules=function(){ +return rs; +}; +o.getListText=function(){ +return lt; +}; +o.getCssText=function(){ +return s; +}; +return o; +},mediaQuery:function(s,mql){ +s=s||""; +var not=false,_14; +var exp=[]; +var _15=true; +var _16=s.match(_3.NOT_WHITESPACE); +for(var i=0;i<_16.length;i++){ +var _17=_16[i]; +if(!_14&&(_17==="not"||_17==="only")){ +if(_17==="not"){ +not=true; +} +}else{ +if(!_14){ +_14=_17; +}else{ +if(_17.charAt(0)==="("){ +var _18=_17.substring(1,_17.length-1).split(":"); +exp[exp.length]={mediaFeature:_18[0],value:_18[1]||null}; +} +} +} +} +return {getList:function(){ +return mql||null; +},getValid:function(){ +return _15; +},getNot:function(){ +return not; +},getMediaType:function(){ +return _14; +},getExpressions:function(){ +return exp; +}}; +},rule:function(s,mql){ +var o={}; +var idx=s.indexOf("{"); +var st=s.substring(0,idx); +var ss=st.split(","); +var ds=[]; +var dts=s.substring(idx+1,s.length-1).split(";"); +for(var i=0;i<dts.length;i++){ +ds[ds.length]=_13.declaration(dts[i],o); +} +o.getMediaQueryList=function(){ +return mql||null; +}; +o.getSelectors=function(){ +return ss; +}; +o.getSelectorText=function(){ +return st; +}; +o.getDeclarations=function(){ +return ds; +}; +o.getPropertyValue=function(n){ +for(var i=0;i<ds.length;i++){ +if(ds[i].getProperty()===n){ +return ds[i].getValue(); +} +} +return null; +}; +return o; +},declaration:function(s,r){ +var idx=s.indexOf(":"); +var p=s.substring(0,idx); +var v=s.substring(idx+1); +return {getRule:function(){ +return r||null; +},getProperty:function(){ +return p; +},getValue:function(){ +return v; +}}; +}}; +var _19=function(el){ +if(typeof el.cssHelperText!=="string"){ +return; +} +var o={mediaQueryLists:[],rules:[],selectors:{},declarations:[],properties:{}}; +var _1a=o.mediaQueryLists; +var ors=o.rules; +var _1b=el.cssHelperText.match(_3.BLOCKS); +if(_1b!==null){ +for(var i=0;i<_1b.length;i++){ +if(_1b[i].substring(0,7)==="@media "){ +_1a[_1a.length]=_13.mediaQueryList(_1b[i]); +ors=o.rules=ors.concat(_1a[_1a.length-1].getRules()); +}else{ +ors[ors.length]=_13.rule(_1b[i]); +} +} +} +var oss=o.selectors; +var _1c=function(r){ +var ss=r.getSelectors(); +for(var i=0;i<ss.length;i++){ +var n=ss[i]; +if(!oss[n]){ +oss[n]=[]; +} +oss[n][oss[n].length]=r; +} +}; +for(i=0;i<ors.length;i++){ +_1c(ors[i]); +} +var ods=o.declarations; +for(i=0;i<ors.length;i++){ +ods=o.declarations=ods.concat(ors[i].getDeclarations()); +} +var ops=o.properties; +for(i=0;i<ods.length;i++){ +var n=ods[i].getProperty(); +if(!ops[n]){ +ops[n]=[]; +} +ops[n][ops[n].length]=ods[i]; +} +el.cssHelperParsed=o; +_4[_4.length]=el; +return o; +}; +var _1d=function(el,s){ +el.cssHelperText=_11(s||el.innerHTML); +return _19(el); +}; +var _1e=function(){ +_5=true; +_4=[]; +var _1f=[]; +var _20=function(){ +for(var i=0;i<_1f.length;i++){ +_19(_1f[i]); +} +var _21=document.getElementsByTagName("style"); +for(i=0;i<_21.length;i++){ +_1d(_21[i]); +} +_5=false; +_8(); +}; +var _22=document.getElementsByTagName("link"); +for(var i=0;i<_22.length;i++){ +var _23=_22[i]; +if(_23.getAttribute("rel").indexOf("style")>-1&&_23.href&&_23.href.length!==0&&!_23.disabled){ +_1f[_1f.length]=_23; +} +} +if(_1f.length>0){ +var c=0; +var _24=function(){ +c++; +if(c===_1f.length){ +_20(); +} +}; +var _25=function(_26){ +var _27=_26.href; +_c(_27,function(_28){ +_28=_11(_28).replace(_3.RELATIVE_URLS,"url("+_27.substring(0,_27.lastIndexOf("/"))+"/$1)"); +_26.cssHelperText=_28; +_24(); +},_24); +}; +for(i=0;i<_1f.length;i++){ +_25(_1f[i]); +} +}else{ +_20(); +} +}; +var _29={mediaQueryLists:"array",rules:"array",selectors:"object",declarations:"array",properties:"object"}; +var _2a={mediaQueryLists:null,rules:null,selectors:null,declarations:null,properties:null}; +var _2b=function(_2c,v){ +if(_2a[_2c]!==null){ +if(_29[_2c]==="array"){ +return (_2a[_2c]=_2a[_2c].concat(v)); +}else{ +var c=_2a[_2c]; +for(var n in v){ +if(v.hasOwnProperty(n)){ +if(!c[n]){ +c[n]=v[n]; +}else{ +c[n]=c[n].concat(v[n]); +} +} +} +return c; +} +} +}; +var _2d=function(_2e){ +_2a[_2e]=(_29[_2e]==="array")?[]:{}; +for(var i=0;i<_4.length;i++){ +_2b(_2e,_4[i].cssHelperParsed[_2e]); +} +return _2a[_2e]; +}; +domReady(function(){ +var els=document.body.getElementsByTagName("*"); +for(var i=0;i<els.length;i++){ +els[i].checkedByCssHelper=true; +} +if(document.implementation.hasFeature("MutationEvents","2.0")||window.MutationEvent){ +document.body.addEventListener("DOMNodeInserted",function(e){ +var el=e.target; +if(el.nodeType===1){ +_a("DOMElementInserted",el); +el.checkedByCssHelper=true; +} +},false); +}else{ +setInterval(function(){ +var els=document.body.getElementsByTagName("*"); +for(var i=0;i<els.length;i++){ +if(!els[i].checkedByCssHelper){ +_a("DOMElementInserted",els[i]); +els[i].checkedByCssHelper=true; +} +} +},1000); +} +}); +var _2f=function(d){ +if(typeof window.innerWidth!="undefined"){ +return window["inner"+d]; +}else{ +if(typeof document.documentElement!="undefined"&&typeof document.documentElement.clientWidth!="undefined"&&document.documentElement.clientWidth!=0){ +return document.documentElement["client"+d]; +} +} +}; +return {addStyle:function(s,_30){ +var el=document.createElement("style"); +el.setAttribute("type","text/css"); +document.getElementsByTagName("head")[0].appendChild(el); +if(el.styleSheet){ +el.styleSheet.cssText=s; +}else{ +el.appendChild(document.createTextNode(s)); +} +el.addedWithCssHelper=true; +if(typeof _30==="undefined"||_30===true){ +cssHelper.parsed(function(_31){ +var o=_1d(el,s); +for(var n in o){ +if(o.hasOwnProperty(n)){ +_2b(n,o[n]); +} +} +_a("newStyleParsed",el); +}); +}else{ +el.parsingDisallowed=true; +} +return el; +},removeStyle:function(el){ +return el.parentNode.removeChild(el); +},parsed:function(fn){ +if(_5){ +_7(fn); +}else{ +if(typeof _4!=="undefined"){ +if(typeof fn==="function"){ +fn(_4); +} +}else{ +_7(fn); +_1e(); +} +} +},mediaQueryLists:function(fn){ +cssHelper.parsed(function(_32){ +fn(_2a.mediaQueryLists||_2d("mediaQueryLists")); +}); +},rules:function(fn){ +cssHelper.parsed(function(_33){ +fn(_2a.rules||_2d("rules")); +}); +},selectors:function(fn){ +cssHelper.parsed(function(_34){ +fn(_2a.selectors||_2d("selectors")); +}); +},declarations:function(fn){ +cssHelper.parsed(function(_35){ +fn(_2a.declarations||_2d("declarations")); +}); +},properties:function(fn){ +cssHelper.parsed(function(_36){ +fn(_2a.properties||_2d("properties")); +}); +},broadcast:_a,addListener:function(n,fn){ +if(typeof fn==="function"){ +if(!_9[n]){ +_9[n]={listeners:[]}; +} +_9[n].listeners[_9[n].listeners.length]=fn; +} +},removeListener:function(n,fn){ +if(typeof fn==="function"&&_9[n]){ +var ls=_9[n].listeners; +for(var i=0;i<ls.length;i++){ +if(ls[i]===fn){ +ls.splice(i,1); +i-=1; +} +} +} +},getViewportWidth:function(){ +return _2f("Width"); +},getViewportHeight:function(){ +return _2f("Height"); +}}; +}(); +domReady(function enableCssMediaQueries(){ +var _37; +var _38={LENGTH_UNIT:/[0-9]+(em|ex|px|in|cm|mm|pt|pc)$/,RESOLUTION_UNIT:/[0-9]+(dpi|dpcm)$/,ASPECT_RATIO:/^[0-9]+\/[0-9]+$/,ABSOLUTE_VALUE:/^[0-9]*(\.[0-9]+)*$/}; +var _39=[]; +var _3a=function(){ +var id="css3-mediaqueries-test"; +var el=document.createElement("div"); +el.id=id; +var _3b=cssHelper.addStyle("@media all and (width) { #"+id+" { width: 1px !important; } }",false); +document.body.appendChild(el); +var ret=el.offsetWidth===1; +_3b.parentNode.removeChild(_3b); +el.parentNode.removeChild(el); +_3a=function(){ +return ret; +}; +return ret; +}; +var _3c=function(){ +_37=document.createElement("div"); +_37.style.cssText="position:absolute;top:-9999em;left:-9999em;"+"margin:0;border:none;padding:0;width:1em;font-size:1em;"; +document.body.appendChild(_37); +if(_37.offsetWidth!==16){ +_37.style.fontSize=16/_37.offsetWidth+"em"; +} +_37.style.width=""; +}; +var _3d=function(_3e){ +_37.style.width=_3e; +var _3f=_37.offsetWidth; +_37.style.width=""; +return _3f; +}; +var _40=function(_41,_42){ +var l=_41.length; +var min=(_41.substring(0,4)==="min-"); +var max=(!min&&_41.substring(0,4)==="max-"); +if(_42!==null){ +var _43; +var _44; +if(_38.LENGTH_UNIT.exec(_42)){ +_43="length"; +_44=_3d(_42); +}else{ +if(_38.RESOLUTION_UNIT.exec(_42)){ +_43="resolution"; +_44=parseInt(_42,10); +var _45=_42.substring((_44+"").length); +}else{ +if(_38.ASPECT_RATIO.exec(_42)){ +_43="aspect-ratio"; +_44=_42.split("/"); +}else{ +if(_38.ABSOLUTE_VALUE){ +_43="absolute"; +_44=_42; +}else{ +_43="unknown"; +} +} +} +} +} +var _46,_47; +if("device-width"===_41.substring(l-12,l)){ +_46=screen.width; +if(_42!==null){ +if(_43==="length"){ +return ((min&&_46>=_44)||(max&&_46<_44)||(!min&&!max&&_46===_44)); +}else{ +return false; +} +}else{ +return _46>0; +} +}else{ +if("device-height"===_41.substring(l-13,l)){ +_47=screen.height; +if(_42!==null){ +if(_43==="length"){ +return ((min&&_47>=_44)||(max&&_47<_44)||(!min&&!max&&_47===_44)); +}else{ +return false; +} +}else{ +return _47>0; +} +}else{ +if("width"===_41.substring(l-5,l)){ +_46=document.documentElement.clientWidth||document.body.clientWidth; +if(_42!==null){ +if(_43==="length"){ +return ((min&&_46>=_44)||(max&&_46<_44)||(!min&&!max&&_46===_44)); +}else{ +return false; +} +}else{ +return _46>0; +} +}else{ +if("height"===_41.substring(l-6,l)){ +_47=document.documentElement.clientHeight||document.body.clientHeight; +if(_42!==null){ +if(_43==="length"){ +return ((min&&_47>=_44)||(max&&_47<_44)||(!min&&!max&&_47===_44)); +}else{ +return false; +} +}else{ +return _47>0; +} +}else{ +if("device-aspect-ratio"===_41.substring(l-19,l)){ +return _43==="aspect-ratio"&&screen.width*_44[1]===screen.height*_44[0]; +}else{ +if("color-index"===_41.substring(l-11,l)){ +var _48=Math.pow(2,screen.colorDepth); +if(_42!==null){ +if(_43==="absolute"){ +return ((min&&_48>=_44)||(max&&_48<_44)||(!min&&!max&&_48===_44)); +}else{ +return false; +} +}else{ +return _48>0; +} +}else{ +if("color"===_41.substring(l-5,l)){ +var _49=screen.colorDepth; +if(_42!==null){ +if(_43==="absolute"){ +return ((min&&_49>=_44)||(max&&_49<_44)||(!min&&!max&&_49===_44)); +}else{ +return false; +} +}else{ +return _49>0; +} +}else{ +if("resolution"===_41.substring(l-10,l)){ +var res; +if(_45==="dpcm"){ +res=_3d("1cm"); +}else{ +res=_3d("1in"); +} +if(_42!==null){ +if(_43==="resolution"){ +return ((min&&res>=_44)||(max&&res<_44)||(!min&&!max&&res===_44)); +}else{ +return false; +} +}else{ +return res>0; +} +}else{ +return false; +} +} +} +} +} +} +} +} +}; +var _4a=function(mq){ +var _4b=mq.getValid(); +var _4c=mq.getExpressions(); +var l=_4c.length; +if(l>0){ +for(var i=0;i<l&&_4b;i++){ +_4b=_40(_4c[i].mediaFeature,_4c[i].value); +} +var not=mq.getNot(); +return (_4b&&!not||not&&!_4b); +} +}; +var _4d=function(mql){ +var mqs=mql.getMediaQueries(); +var t={}; +for(var i=0;i<mqs.length;i++){ +if(_4a(mqs[i])){ +t[mqs[i].getMediaType()]=true; +} +} +var s=[],c=0; +for(var n in t){ +if(t.hasOwnProperty(n)){ +if(c>0){ +s[c++]=","; +} +s[c++]=n; +} +} +if(s.length>0){ +_39[_39.length]=cssHelper.addStyle("@media "+s.join("")+"{"+mql.getCssText()+"}",false); +} +}; +var _4e=function(_4f){ +for(var i=0;i<_4f.length;i++){ +_4d(_4f[i]); +} +if(ua.ie){ +document.documentElement.style.display="block"; +setTimeout(function(){ +document.documentElement.style.display=""; +},0); +setTimeout(function(){ +cssHelper.broadcast("cssMediaQueriesTested"); +},100); +}else{ +cssHelper.broadcast("cssMediaQueriesTested"); +} +}; +var _50=function(){ +for(var i=0;i<_39.length;i++){ +cssHelper.removeStyle(_39[i]); +} +_39=[]; +cssHelper.mediaQueryLists(_4e); +}; +var _51=0; +var _52=function(){ +var _53=cssHelper.getViewportWidth(); +var _54=cssHelper.getViewportHeight(); +if(ua.ie){ +var el=document.createElement("div"); +el.style.position="absolute"; +el.style.top="-9999em"; +el.style.overflow="scroll"; +document.body.appendChild(el); +_51=el.offsetWidth-el.clientWidth; +document.body.removeChild(el); +} +var _55; +var _56=function(){ +var vpw=cssHelper.getViewportWidth(); +var vph=cssHelper.getViewportHeight(); +if(Math.abs(vpw-_53)>_51||Math.abs(vph-_54)>_51){ +_53=vpw; +_54=vph; +clearTimeout(_55); +_55=setTimeout(function(){ +if(!_3a()){ +_50(); +}else{ +cssHelper.broadcast("cssMediaQueriesTested"); +} +},500); +} +}; +window.onresize=function(){ +var x=window.onresize||function(){ +}; +return function(){ +x(); +_56(); +}; +}(); +}; +var _57=document.documentElement; +_57.style.marginLeft="-32767px"; +setTimeout(function(){ +_57.style.marginTop=""; +},20000); +return function(){ +if(!_3a()){ +cssHelper.addListener("newStyleParsed",function(el){ +_4e(el.cssHelperParsed.mediaQueryLists); +}); +cssHelper.addListener("cssMediaQueriesTested",function(){ +if(ua.ie){ +_57.style.width="1px"; +} +setTimeout(function(){ +_57.style.width=""; +_57.style.marginLeft=""; +},0); +cssHelper.removeListener("cssMediaQueriesTested",arguments.callee); +}); +_3c(); +_50(); +}else{ +_57.style.marginLeft=""; +} +_52(); +}; +}()); +try{ +document.execCommand("BackgroundImageCache",false,true); +} +catch(e){ +} +
diff --git a/content/notices/.gitignore b/content/notices/.gitignore new file mode 100644 index 0000000..dd44972 --- /dev/null +++ b/content/notices/.gitignore @@ -0,0 +1 @@ +*.md diff --git a/example.md b/example.md new file mode 100644 index 0000000..64da7c9 --- /dev/null +++ b/example.md @@ -0,0 +1,25 @@ +--- +title: Example Notice +active: true +type: maintenance +created_at: 2012-02-20 10:00 +eta: 2012-02-22 10:00 +expire: 2012-03-20 10:00 +kind: article +affects: [overlays, forums, bugzilla] +force_state: maintenance +--- + +Here you can add text in the markdown format. + +Parameters above: +title: self-explanatory +active: set this to false to completely hide the notice +type: (maintenance|information|outage) sets the icon +created_at: self-explanatory +eta: estimated time the service is restored (optional) +expire: when to hide the notice. defaults to one week (optional) +kind: set to 'article' (mandatory!) +affects: array of services this notice affects (TODO list, optional) +force_state: (maintenance|up|down) force the state of all services this notice applies to to this state (optional) + diff --git a/layouts/_post.haml b/layouts/_post.haml new file mode 100644 index 0000000..16c7ff3 --- /dev/null +++ b/layouts/_post.haml @@ -0,0 +1,21 @@ +.row.post + %h3 + =item_icon(item[:type]) + =item[:title] + .grey + %table.dates + %tr + %td Posted at + %td=item[:created_at] + - if item.attributes.has_key? :eta + %tr + %td Estimated time of recovery + %td=item[:eta] + - if is_expired? item + %tr{ :colspan => '2'} + %td + %img{ :src => base_url + 'img/information.png', :alt => 'information'} + This notice is + %strong expired. + The service has been restored. + ~ yield diff --git a/layouts/default.haml b/layouts/default.haml new file mode 100644 index 0000000..e5f5938 --- /dev/null +++ b/layouts/default.haml @@ -0,0 +1,38 @@ +!!! 5 +%html + %head + %title Gentoo Linux Infrastructure status + %meta{ :charset => 'utf-8' } + %meta{ :name => 'viewport', :content => 'width=device-width, initial-scale=1.0' } + /[if lte IE 9] + %link{ :rel => 'stylesheet', :href => '/css/ie.css', :type => 'text/css', :media => 'screen' } + %link{ :rel => 'stylesheet', :href => '/css/1140.css', :type => 'text/css', :media => 'screen' } + %link{ :rel => 'stylesheet', :href => '/css/screen.css', :type => 'text/css', :media => 'screen' } + %link{ :rel => 'stylesheet', :href => 'http://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic,600', :type => 'text/css' } + %link{ :rel => 'alternate', :href => '/atom.xml', :type => 'application/atom+xml', :title => 'Atom Feed' } + %script{ :src => '/js/css3-mediaqueries.js', :type => 'text/javascript'} + %body + .container.header + .row + .twelvecol.last + %img{ :src => '/img/site_logo.png', :alt => 'Gentoo Linux Infrastructure status' } + .container.site-title + .row + .twelvecol.last + %span.right + %a{ :href => '/atom.xml', :title => 'Subscribe to the Atom feed' } + %img{ :src => '/img/feed.png', :alt => 'Atom feed' } + %h1 Gentoo Linux Infrastructure Status + + = yield + .container#footer + .row + .sixcol + Copyright © Gentoo Foundation, Inc. · Contents licensed under the CC-BY-SA 3.0 license + .sixcol.last + This site is powered by: + %a{ :href => 'http://nanoc.stoneship.org/'} nanoc + · + %a{ :href => 'http://p.yusukekamiyamane.com/'} the Fugue iconset + · + %a{ :href => 'http://cssgrid.net/' } the 1140 grid diff --git a/lib/default.rb b/lib/default.rb new file mode 100644 index 0000000..a4df0cc --- /dev/null +++ b/lib/default.rb @@ -0,0 +1,2 @@ +# All files in the 'lib' directory will be loaded +# before nanoc starts compiling. diff --git a/lib/helpers.rb b/lib/helpers.rb new file mode 100644 index 0000000..a66457f --- /dev/null +++ b/lib/helpers.rb @@ -0,0 +1,136 @@ +include Nanoc::Helpers::Blogging +include Nanoc::Helpers::Rendering +require 'date' + +# Defining state constants +module State + UP=1 + DOWN=2 + WARNING=3 +end + +def service_icons(service) + content = "" + + if service_has_notices?(service) + content << notice_icon + " " + end + + unless (forced_state = get_forced_state(service)) == nil + content << status_icon(forced_state) + return content + end + + case ServiceRegistry.instance.services[service] + when State::UP + content << status_icon('up') + when State::WARNING + content << status_icon('warning') + when State::DOWN + content << status_icon('down') + else + content << status_icon('na') + end + + content +end + +def status_icon(status) + case status.to_s + when 'up' + return '<img src="/img/status_up.png" alt="The service is up and running." title="The service is up and running." />' + when 'down' + return '<img src="/img/status_down.png" alt="The service is down." title="The service is down." />' + when 'warning' + return '<img src="/img/status_warning.png" alt="There are issues with the service." title="There are issues with the service." />' + when 'maintenance' + return '<img src="/img/maintenance.png" alt="The service is undergoing scheduled maintenance." title="The service is undergoing scheduled maintenance." />' + else + return '<img src="/img/na.png" alt="No data available." title="No data available." />' + end +end + +def notice_icon + return '<img src="/img/notice.png" alt="There are notices regarding this service posted below." title="There are notices regarding this service posted below." />' +end + +def item_icon(type) + case type.to_s + when 'maintenance' + return '<img src="' + base_url + 'img/maintenance.png" alt="Scheduled maintenance" title="Scheduled maintenance" />' + when 'outage' + return '<img src="' + base_url + '/img/outage.png" alt="Unplanned outage" title="Unplanned outage" />' + when 'information' + return '<img src="' + base_url + '/img/information.png" alt="General information" title="General information" />' + end +end + +# Compiles all active notices into one piece of HTML +def notices + content="" + + sorted_articles.each do |notice| + next if is_expired? notice + + content += notice.compiled_content(:snapshot => :single_post) + end + + content +end + +# Are there any notices for the service? +def service_has_notices?(service) + articles.each do |notice| + next if is_expired? notice + + if notice.attributes.has_key? :affects and notice[:affects].include? service + return true + end + end + + false +end + +def get_forced_state(service) + return nil unless service_has_notices?(service) + + sorted_articles.each do |notice| + next if is_expired? notice + + if notice.attributes.has_key? :affects and notice[:affects].include? service + return notice[:force_state] if notice.attributes.has_key? :force_state + end + end +end + +# Filters expired items and items w/o expiration date that are older than a week. +def is_expired?(notice) + if notice.attributes.has_key? :active + return true if notice[:active] != true + end + + if notice.attributes.has_key? :expire + expire_date = DateTime.parse(notice[:expire]) + + DateTime.now > expire_date + else + creation_date = DateTime.parse(notice[:created_at]) + date_diff = DateTime.now - creation_date + + date_diff.to_i > 7 + end +end + +def feed_proc + lambda do |notice| + notice.compiled_content(:snapshot => :single_post) + end +end + +def feed_articles + articles.select {|n| not is_expired? n} +end + +def base_url + @site.config[:base_url] + '/' +end diff --git a/lib/service-dsl.rb b/lib/service-dsl.rb new file mode 100644 index 0000000..42f94d4 --- /dev/null +++ b/lib/service-dsl.rb @@ -0,0 +1,73 @@ +require 'singleton' +require 'json' + +module HelperMethods + # Checks if all hosts are up + def all_hosts_up?(hosts) + hosts.each do |host| + return false unless status_data['hosts'][host]['current_state'] == 0 + end + + true + end + + def host_up?(host) + status_data['hosts'][host]['current_state'] == 0 + end + + def host_flapping?(host) + status_data['hosts'][host]['is_flapping'] != 0 + end + + # Checks if the service is up + def service_up?(host, service) + status_data['services'][host][service]['current_state'] == 0 + end + + def service_flapping?(host, service) + status_data['services'][host][service]['is_flapping'] != 0 + end + + def default(host, service = nil) + if service == nil + if host_flapping? host + State::WARNING + elsif host_up? host + State::UP + else + State::DOWN + end + else + if service_flapping? host, service + State::WARNING + elsif service_up? host, service + State::UP + else + State::DOWN + end + end + end +end + +class ServiceRegistry + StatusSource = "/tmp/status.json" + + include Singleton + include HelperMethods + attr_reader :services, :status_data + + + def initialize + @services = {} + + @status_data = JSON.parse(File.read(StatusSource)) + end + + def service(name, &block) + @services[name] = block.call + end +end + +def Services(&block) + ServiceRegistry.instance.instance_eval(&block) +end diff --git a/lib/services.rb b/lib/services.rb new file mode 100644 index 0000000..35b1127 --- /dev/null +++ b/lib/services.rb @@ -0,0 +1,93 @@ +# Accessing JSON data works via status_data +# Return State::UP, State::Down, or State::Warning +# Nagios states: 0 (ok), 1 (warning), 2 (critical), 3 (unknown), 4 (dependent) + +Services do + service 'www' do + if service_flapping? 'ani', 'http_www' and service_flapping? 'auklet', 'http_www' and service_flapping? 'loon', 'http_www' + State::WARNING + elsif service_up? 'ani', 'http_www' or service_up? 'auklet', 'http_www' or service_up? 'loon', 'http_www' + State::UP + else + State::DOWN + end + end + + service 'forums' do + if service_flapping? 'godwit', 'http_forums' or service_flapping? 'gannet', 'http_forums' + State::WARNING + elsif service_up? 'godwit', 'http_forums' or service_up? 'gannet', 'http_forums' + State::UP + else + State::DOWN + end + end + + service 'wiki' do + default 'bittern', 'http_wiki' + end + + service 'planet' do + default 'barbet', 'http_planet' + end + + service 'pgo' do + default 'barbet', 'http_packages' + end + + service 'lists' do + default 'pigeon' + end + + service 'archives' do + default 'finch' + end + + service 'cvs' do + default 'flycatcher', 'ssh_cvs' + end + + service 'devmanual' do + default 'barbet', 'http_devmanual' + end + + service 'overlays' do + default 'hornbill', 'http_overlays' + end + + service 'tinderbox' do + default 'tinderbox.dev' + end + + service 'sources' do + default 'motmot', 'http_sources' + end + + service 'bugzilla' do + if service_flapping? 'yellowbishop', 'http_bugs' or service_flapping? 'yellowleg', 'http_bugs' + State::WARNING + elsif service_up? 'yellowbishop', 'http_bugs' and service_up? 'yellowleg', 'http_bugs' + State::UP + elsif service_up? 'yellowbishop', 'http_bugs' or service_up? 'yellowleg', 'http_bugs' + State::WARNING + else + State::DOWN + end + end + + service 'dgo_ssh' do + default 'woodpecker', 'ssh_dgo' + end + + service 'dgo_http' do + nil + end + + service 'dgo_smtp' do + nil + end + + service 'dgo_mbox' do + nil + end +end |