text:
import * as express from 'express'
import * as expressWinston from 'express-winston'
import * as cors from 'cors'

import { ProofChecker } from './ProofChecker'
import { getChallengeText, LATEST_AUTH_VERSION } from './authentication'
import { HubServer } from './server'
import { getDriverClass, logger, AsyncMutexScope } from './utils'
import { DriverModel } from './driverModel'
import * as errors from './errors'
import { HubConfigInterface } from './config'

function writeResponse(res: express.Response, data: any, statusCode: number) {
  res.writeHead(statusCode, {'Content-Type' : 'application/json'})
  res.write(JSON.stringify(data))
  res.end()
}

export function makeHttpServer(config: HubConfigInterface): { app: express.Application, server: HubServer, driver: DriverModel, asyncMutex: AsyncMutexScope } {

  const app: express.Application = express()

  const asyncMutex = new AsyncMutexScope()

  // Handle driver configuration
  let driver: DriverModel

  if (config.driverInstance) {
    driver = config.driverInstance
  } else if (config.driverClass) {
    driver = new config.driverClass(config)
  } else if (config.driver) {
    const driverClass = getDriverClass(config.driver)
    driver = new driverClass(config)
  } else {
    throw new Error('Driver option not configured')
  }

  const proofChecker = new ProofChecker(config.proofsConfig)
  const server = new HubServer(driver, proofChecker, config)

  // Instantiate server logging with Winston
  app.use(expressWinston.logger({
    winstonInstance: logger }))

  const corsConfig = cors({
    origin: '*',
    // Set the Access-Control-Max-Age header to 24 hours.
    maxAge: 86400,
    methods: 'DELETE,POST,GET,OPTIONS,HEAD',
    // Allow the client to include match headers in http requests
    // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
    allowedHeaders: 'Authorization,Content-Type,If-Match,If-None-Match'
  })

  app.use(corsConfig)

  // Enabling CORS Pre-Flight
  // https://www.npmjs.com/package/cors#enabling-cors-pre-flight
  app.options('*', corsConfig)

  // sadly, express doesn't like to capture slashes.
  //  but that's okay! regexes solve that problem
  app.post(/^\/store\/([a-zA-Z0-9]+)\/(.+)/, (
    req: express.Request,
    res: express.Response
  ) => {
    let filename = req.params[1]
    if (filename.endsWith('/')){
      filename = filename.substring(0, filename.length - 1)
    }
    const address = req.params[0]
    const endpoint = `${address}/${filename}`

    const handleRequest = async () => {
      try {
        const responseData = await server.handleRequest(address, filename, req.headers, req)
        writeResponse(res, responseData, 202)
      } catch (err) {
        logger.error(err)
        if (err instanceof errors.ValidationError) {
          writeResponse(res, { message: err.message, error: err.name }, 401)
        } else if (err instanceof errors.AuthTokenTimestampValidationError) {
          writeResponse(res, { message: err.message, error: err.name }, 401)
        } else if (err instanceof errors.BadPathError) {
          writeResponse(res, { message: err.message, error: err.name }, 403)
        } else if (err instanceof errors.NotEnoughProofError) {
          writeResponse(res, { message: err.message, error: err.name }, 402)
        } else if (err instanceof errors.ConflictError) {
          writeResponse(res, { message: err.message, error: err.name }, 409)
        } else if (err instanceof errors.PayloadTooLargeError) {
          writeResponse(res, { message: err.message, error: err.name }, 413)
        } else if (err instanceof errors.PreconditionFailedError) {
          writeResponse(res, { message: err.message, error: err.name, etag: err.expectedEtag }, 412)
        } else {
          writeResponse(res, { message: 'Server Error' }, 500)
        }
      }
    }

    try {
      if (!asyncMutex.tryAcquire(endpoint, handleRequest)) {
        const errMsg = `Concurrent operation (store) attempted on ${endpoint}`
        logger.error(errMsg)
        writeResponse(res, {
          message: errMsg,
          error: errors.ConflictError.name
        }, 409)
      }
    } catch (err) {
      logger.error(err)
      writeResponse(res, { message: 'Server Error' }, 500)
    }

  })

  app.delete(/^\/delete\/([a-zA-Z0-9]+)\/(.+)/, (
    req: express.Request,
    res: express.Response
  ) => {
    let filename = req.params[1]
    if (filename.endsWith('/')){
      filename = filename.substring(0, filename.length - 1)
    }
    const address = req.params[0]
    const endpoint = `${address}/${filename}`

    const handleRequest = async () => {
      try {
        await server.handleDelete(address, filename, req.headers)
        res.writeHead(202)
        res.end()
      } catch (err) {
        logger.error(err)
        if (err instanceof errors.ValidationError) {
          writeResponse(res, { message: err.message, error: err.name }, 401)
        } else if (err instanceof errors.AuthTokenTimestampValidationError) {
          writeResponse(res, { message: err.message, error: err.name  }, 401)
        } else if (err instanceof errors.BadPathError) {
          writeResponse(res, { message: err.message, error: err.name  }, 403)
        } else if (err instanceof errors.DoesNotExist) {
          writeResponse(res, { message: err.message, error: err.name  }, 404)
        } else if (err instanceof errors.NotEnoughProofError) {
          writeResponse(res, { message: err.message, error: err.name  }, 402)
        } else {
          writeResponse(res, { message: 'Server Error' }, 500)
        }
      }
    }

    try {
      if (!asyncMutex.tryAcquire(endpoint, handleRequest)) {
        const errMsg = `Concurrent operation (delete) attempted on ${endpoint}`
        logger.error(errMsg)
        writeResponse(res, {
          message: errMsg,
          error: errors.ConflictError.name
        }, 409)
      }
    } catch (err) {
      logger.error(err)
      writeResponse(res, { message: 'Server Error' }, 500)
    }

  })

  app.post(
    /^\/list-files\/([a-zA-Z0-9]+)\/?/, express.json({ limit: 4096 }),
    (req: express.Request, res: express.Response) => {
      // sanity check... should never be reached if the express json parser is working correctly
      if (parseInt(req.headers['content-length']) > 4096) {
        writeResponse(res, { message: 'Invalid JSON: too long'}, 400)
        return
      }

      const address = req.params[0]
      const requestBody = req.body
      const page = requestBody.page ? requestBody.page : null
      const stat = !!requestBody.stat

      server.handleListFiles(address, page, stat, req.headers)
        .then((files) => {
          writeResponse(res, { entries: files.entries, page: files.page }, 202)
        })
        .catch((err: any) => {
          logger.error(err)
          if (err instanceof errors.ValidationError) {
            writeResponse(res, { message: err.message, error: err.name }, 401)
          } else if (err instanceof errors.AuthTokenTimestampValidationError) {
            writeResponse(res, { message: err.message, error: err.name  }, 401)
          } else {
            writeResponse(res, { message: 'Server Error' }, 500)
          }
        })
    })

  app.post(
    /^\/revoke-all\/([a-zA-Z0-9]+)\/?/,
    express.json({ limit: 4096 }),
    (req: express.Request, res: express.Response) => {
      // sanity check... should never be reached if the express json parser is working correctly
      if (parseInt(req.headers['content-length']) > 4096) {
        writeResponse(res, { message: 'Invalid JSON: too long'}, 400)
        return
      }

      if (!req.body || !req.body.oldestValidTimestamp) {
        writeResponse(res, { message: 'Invalid JSON: missing oldestValidTimestamp'}, 400)
        return
      }

      const address = req.params[0]
      const oldestValidTimestamp: number = parseInt(req.body.oldestValidTimestamp)

      if (!Number.isFinite(oldestValidTimestamp) || oldestValidTimestamp < 0) {
        writeResponse(res, { message: 'Invalid JSON: oldestValidTimestamp is not a valid integer'}, 400)
        return
      }

      server.handleAuthBump(address, oldestValidTimestamp, req.headers)
        .then(() => {
          writeResponse(res, { status: 'success' }, 202)
        })
        .catch((err: any) => {
          logger.error(err)
          if (err instanceof errors.ValidationError) {
            writeResponse(res, { message: err.message, error: err.name  }, 401)
          } else if (err instanceof errors.BadPathError) {
            writeResponse(res, { message: err.message, error: err.name  }, 403)
          } else {
            writeResponse(res, { message: 'Server Error' }, 500)
          }
        })
    })

  app.get('/hub_info/', (req: express.Request,
                         res: express.Response) => {
    const challengeText = getChallengeText(server.serverName)
    if (challengeText.length < 10) {
      return writeResponse(res, { message: 'Server challenge text misconfigured' }, 500)
    }
    const readURLPrefix = server.getReadURLPrefix()
    writeResponse(res, { 'challenge_text': challengeText,
                         'latest_auth_version': LATEST_AUTH_VERSION,
                         'max_file_upload_size_megabytes': server.maxFileUploadSizeMB,
                         'read_url_prefix': readURLPrefix }, 200)
  })

  // Instantiate express application
  return { app, server, driver, asyncMutex }
}


text:
===============
Remove Old Eggs
===============

Question
--------

ADDQUESTION

Solution
--------

.. literalinclude:: ../../languages/python/software_engineering_remove_old_eggs.py
   :language: python
   :tab-width: 4

.. runcode:: ../../languages/python/software_engineering_remove_old_eggs.py
   :language: python
   :codesite: ideone

Explanation
===========

.. git_changelog::

.. seealso::

   * :python-suggest-improve:`software_engineering_remove_old_eggs.py`
   * :python-better-explain:`software_engineering_remove_old_eggs.rst`

redpajama_set_name: RedPajamaGithub


text:
/* Set up all the web-fonts we host */
@font-face {
  font-family: 'engravers_gothic_fsregular';
  src: url("../fonts/EngraversGothic-Regular-webfont.eot");
  src: url("../fonts/EngraversGothic-Regular-webfont.eot?#iefix") format('embedded-opentype'),
       url("../fonts/EngraversGothic-Regular-webfont.woff") format('woff'),
       url("../fonts/EngraversGothic-Regular-webfont.ttf") format('truetype'),
       url("../fonts/EngraversGothic-Regular-webfont.svg#engravers_gothic_fsregular") format('svg');
  font-weight: normal;
  font-style: normal;
}

@font-face {
  font-family: 'volkswagen_serialregular';
  src: url("../fonts/VolkswagenSerial-Regular.otf");
  src: url("../fonts/VolkswagenSerial-Regular.ttf") format('truetype'),
       url("../fonts/VolkswagenSerial-Regular.svg#volkswagen_serialregular") format('svg');
  font-weight: normal;
  font-style: normal;
}

@font-face {
  font-family: 'varela_round_regular';
  src: url("../fonts/VarelaRound-Regular.ttf");
  font-weight: normal;
  font-style: normal;
}

/* font and css for combining-diacritical things */
@font-face {
  font-family: 'combining-diacritical';
  src:  url('/fonts/combining-diacritical.ttf') format('truetype');
  font-weight: normal;
  font-style: normal;
}

.cd {
  display: inline-block;
  font: normal normal normal 14px/1 'combining-diacritical';
  font-size: inherit;
  text-rendering: auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transform: translate(0, 0);
}

/* Basic style */
/*
html, body {
  height: 100%;
  font-family: "Segoe UI", "Arial", "Helvetica", sans-serif;
*/

/* Prevent highlighting/selecting text */
.no-copy-pasta {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  cursor: default;
}

.body { margin: 10px; }

.nav, .pagination, .carousel, .panel-title a { cursor: pointer; }

/* Wrapper for page content to push down footer */
.wrap {
  min-height: 100%;
  height: auto !important;
  height: 100%;
  margin: 0 auto -70px; /* Negative indent footer by its height */
  padding: 0 0 60px; /* Pad bottom by footer height */
}

/* The keyboard background */
.keyboard {
  padding: 4px;
  border-radius: 12px;
  margin-top: 10px;
  margin-bottom: 10px;
  border: dashed 1px #ddd;

/*
  border-color: red;
  border-size: 2px;
*/

  /* shrink-to-fit: http://stackoverflow.com/questions/450903/how-to-make-div-not-larger-than-its-contents?rq=1#comment-66847556 */
  display: inline-block;
}
.keyboard .keyboard-bg {
  position: inherit;
  border: solid 1px #ddd;
  padding: 9px;
  box-sizing: content-box;
  border-radius: 6px;
  min-width: 56px;
  min-height: 56px;
}
.keyboard-bg div {
  position: absolute;
  border-color: black;
  box-sizing: border-box;
  background-clip: padding-box;
}
.keyboard .hover .keyborder,
.keyboard .hover .decal .keyborder { border-color: green !important; border-style: solid; }
.keyboard .selected .keyborder,
.keyboard .selected .decal .keyborder { border-color: red !important; border-style: solid; }
.keyboard .ghosted { opacity: 0.5; }
.keyboard .decal .keyborder { border-style: none !important; background: transparent !important; }
.keyboard .hover .decal .keyborder,
.keyboard .selected .decal .keyborder { border-style: dashed !important; border-width: 1px; }

/* Key labels */
.keylabel>div { display: table-cell; position: static !important; }
/* Vertical alignment */
.keylabel0>div, .keylabel1>div, .keylabel2>div { vertical-align: top; }
.keylabel3>div, .keylabel4>div, .keylabel5>div { vertical-align: middle; }
.keylabel6>div, .keylabel7>div, .keylabel8>div { vertical-align: bottom; }
.keylabel9, .keylabel10, .keylabel11 { top: 100%; margin-top: -1px; font-size: 10px !important; max-height: 1em !important; white-space: nowrap; overflow: hidden; }
/* Horizontal  alignment */
.keylabel0>div, .keylabel3>div, .keylabel6>div, .keylabel9>div { text-align: left; }
.keylabel1>div, .keylabel4>div, .keylabel7>div, .keylabel10>div { text-align: center; }
.keylabel2>div, .keylabel5>div, .keylabel8>div, .keylabel11>div { text-align: right; }
/* Label Sizes */
/*
for i in (1..9) {
  .keylabel.textsize{i} {
    font-size: (6+2*i)px;
    line-height: 1em;
  }
}
*/
  .keylabel.textsize1 {
    font-size: 8px;
    line-height: 1em;
  }
  .keylabel.textsize2 {
    font-size: 10px;
    line-height: 1em;
  }
  .keylabel.textsize3 {
    font-size: 12px;
    line-height: 1em;
  }
  .keylabel.textsize4 {
    font-size: 14px;
    line-height: 1em;
  }
  .keylabel.textsize5 {
    font-size: 16px;
    line-height: 1em;
  }
  .keylabel.textsize6 {
    font-size: 18px;
    line-height: 1em;
  }
  .keylabel.textsize7 {
    font-size: 20px;
    line-height: 1em;
  }
  .keylabel.textsize8 {
    font-size: 22px;
    line-height: 1em;
  }
  .keylabel.textsize9 {
    font-size: 24px;
    line-height: 1em;
  }

.keylabels {
  font-family: "Segoe UI", "Helvetica", "Arial", sans-serif;
}
.keylabel hr { display: inline; }
.keylabel hr:before {
  position: relative;
  display: block;
  overflow: hidden;
  white-space: nowrap;
  content: "\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500";
}

/* Keycap-Profile Modifications */
.SA .keylabels, .DSA .keylabels {
  font-family: 'engravers_gothic_fsregular'; /* substitute for Gorton Modified */
}

.DSA .keylabel9, .DSA .keylabel10, .DSA .keylabel11,
.SA .keylabel9, .SA .keylabel10, .SA .keylabel11 {
  margin-top: -2px;
  font-size: 9px !important;
}
.DCS .keytop, .OEM .keytop {
  background: linear-gradient(to right, #00000000 0%, #0000001A 40%, #0000001A 60%, #00000000 100%);
  background-repeat: no-repeat;
}
.DSA .keytop, .SA .keytop {
  background: radial-gradient(ellipse at center, #0000001A 0%, #0000001A 10%, #00000000 100%);
  background-repeat: no-repeat;
}

.DCS.SPACE .keytop, .OEM.SPACE .keytop, .DSA.SPACE .keytop, .SA.SPACE .keytop {
  background: linear-gradient(to bottom, #0000001A 0%, #00000000 20%, #00000000 40%, #0000001A 100%);
  background-repeat: no-repeat;
}
.DSA.DISH .keytop, .DSA.HOMING .keytop, .SA.HOMING .keytop {
  background: radial-gradient(circle, #0000001C 50%, #0000000A 60%);
  background-repeat: no-repeat;
}
.HOMING .keylabels {
  background-image: url("nub.png");
  background-repeat: no-repeat;
  background-position: center 90%;
}
.DSA.HOMING .keylabels, .SA.HOMING .keylabels { background-image: none; }

/* color swatches */
.swatches, .glyphs { list-style-type: none; margin: 0px; padding: 0px; }
.swatch, .glyph {
  display: inline-block;
  position: relative;
  width: 16px;
  height: 32px;
  border: solid 1px #888;
  margin-right: -1px;
  margin-bottom: -6px;
  padding: 0px;
}
.glyph {font-family: 'combining-diacritical';
  width: 1.7em;
  text-align: center;
  padding-top: 0px;
  font-size: 1.618em;
  border: solid 1px #eee;
  background-color: #fff;
}
.glyph:hover { background-color: #eee; }
.glyph.selected { background-color: #eef !important; }

#glyphScroller {
  width: 100%;
  overflow-y: scroll !important;
  overflow-x: hidden !important;
  max-height: 230px;
  border: solid 1px #ccc;
  padding: 4px;
}

.swatches.disabled .swatch { background-color: rgb(235,235,228) !important; }

.swatch .highlight { display: none; }
.swatch.selected-bg .highlight.bg { display: block; z-index: 100; width: 6px; height: 6px; border: solid 1px black; background: white; opacity: 0.75; position: absolute; left: 7px; top: 23px; }
.swatch.selected-fg .highlight.fg { display: block; z-index: 100; width: 6px; height: 6px; border: solid 1px white; background: black; opacity: 0.75; position: absolute; left: 1px; top: 23px; }

/* general styles */
.hidden { display: none; }
.error { border: solid 2px rgb(217,83,79) !important; }
#selectionRectangle { position: absolute; border: dashed 2px red; }
#rotationCrosshairs {
  display: none;
  position: absolute;
  margin: 0px;
  padding: 0px;
  font-size: 25px;
  line-height: 23px;
  width: 25px;
  height: 25px;
  color: black;
  text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;
}

#rawdata, #rawdata-error, #customstyles, #customstyles-error, #noteseditor, #picker-html, #summary { font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace; line-height: 1.42857143 !important; }
#rawdata, #rawdata-error, #customstyles, #customstyles-error, #noteseditor, #picker-html { border: solid 1px #ccc; }

#rawdata, #customstyles { width: 100%; height: 400px; }
#noteseditor { height: 275px; }
#rawdata-error, #customstyles-error { white-space: pre; }
#summary { margin-left: 20px; padding-left: 20px; }

#tab-content {
    border-left: 1px solid #ddd;
    border-right: 1px solid #ddd;
    border-bottom: 1px solid #ddd;
    padding-top: 15px;
    padding-bottom: 15px;
    margin-left: 0px;
}
#properties.row { padding-left: 30px; }

/* Tooltip modifications */
.hint--rounded:after { width: 300px; }
.hint:after, [data-hint]:after { white-space: pre-line; }
.hint:before, .hint:after, [data-hint]:before, [data-hint]:after { -webkit-transition: 0.05s ease; -moz-transition: 0.05s ease; transition: 0.05s ease; }
.hint--no-animate:before, .hint--no-animate:after { transition: 0ms !important; }

/* Help Dialog */
.modal-xl .modal-dialog { width: 80vw; }
.modal-xxl .modal-dialog { width: 90vw; }

/* Our "README" dialog; we want the body of the dialog itself to be scrollable */
.markdownDialog .modal-dialog { margin: 30px auto; } /*60px*/
.markdownDialog .modal-header { height: 55px; }
.markdownDialog .modal-footer { height: 74px; margin-top: 0px; }
.markdownDialog .modal-body {
  padding-bottom: 15px;
  height: calc(100vh - 205px) !important;
  overflow-y: auto !important;
}

.drag-over { border: dotted 3px red !important; box-sizing: border-box; }

/* Only show the keyboard layout itself when printing */
@media print {
  html, body { overflow: hidden; height: 100%; margin: 0 !important; padding: 0 !important; }
  #wrap > .navbar, #wrap > .body > .btn-group, .keyboard ~ *, .keyboard + *, #footer, #helpDialog, #markdownDialog, #summary { display: none; margin: 0 !important; padding: 0 !important; }
  div.body { margin: 0 !important; padding: 0 !important; }
  a { color: black; text-decoration: none; }
  .keyboard {
    border: none;
    background-color: inherit !important;
    transform: scale(0.75,0.75);
    position: absolute !important;
    left: 0px;
    top: 0px;
    padding-left: 0px; padding-top: 0px;
  }
}

/* the default (-15px) causes overflow problems */
.navbar-right { margin-right: 0; }

.use-default:after {
  content: "\d7"; /* × */
  right: 0px;
  bottom: -4px;
  position: absolute;
}

/* Combining rectangle glyph */
.combine-rect:before {
  content: '\25AD';
  font-style: normal;
  /*margin: 0 -0.66em 0 -0.33em;*/
}

.avatar {
  max-width: 1.25em;
  max-height: 1.25em;
}

/* nested dropdown menu lists; see bootstrap.css */
.dropdown-menu ul {
  list-style: none;
  margin: 2px 0 0;
  padding: 5px 0;
}
.dropdown-menu ul > li > a {
  display: block;
  padding: 3px 20px;
  clear: both;
  font-weight: normal;
  line-height: 1.42857143;
  color: #333;
  white-space: nowrap;
}
.dropdown-menu ul > li > a:hover,
.dropdown-menu ul > li > a:focus {
  color: #262626;
  text-decoration: none;
  background-color: #f5f5f5;
}
/* button size between sm & xs; meant for inline forms */
.btn-sm-form,
.btn-group-sm-form > .btn {
  padding: 3px 8px;
  font-size: 12px;
  line-height: 1.5;
  border-radius: 3px;
}

.dropdown-fixedwidth {
  width:110px;
  max-width:110px;
  height: 26px;
}
.dropdown-fixedwidth>:first-child {
  display: block;
  left: 5px;
  width: calc(100% - 12px);
  text-align: left;
  overflow: hidden;
}
.dropdown-fixedwidth .caret {
  display: block;
  position: absolute;
  right: 5px;
  top: 11px;
}

.dropdown-select {
  max-height: 40vh;
  overflow-y: auto;
}

table.summarytable {
  border-collapse: collapse;
  margin-top: 1em;
}

table.summarytable th, table.summarytable td {
  border: 1px solid black;
  padding: 2px 5px;
}

/* -------------------------------------------- */

.keyboard.keyboard-ibmpc .keyboard-bg {
  background-color:#eeeeee;
  border-radius: 6px;
}

.keyboard.keyboard-macbook .keyboard-bg {
   background-color:#dbdbdb;
   border-radius: 6px 6px 12px 12px / 18px 18px 12px 12px;
}

.keyboard .keyboard-bg .keyborder-ibmpc-std {
   width: 54px; height: 54px; border-style: solid; border-width: 1px; border-color: black; border-radius: 5px; background-color: #cccccc;
}

.keyboard .keyboard-bg .keytop-ibmpc-std {
    width: 42px; height: 42px; border-style: solid; border-width: 1px; border-color: rgba(0,0,0,0.1); background-color: #fcfcfc; border-radius: 3px;
}

.keyboard .keyboard-bg .keylabels-ibmpc-std {
	 width: 42px; height: 42px; padding: 3px;
}
.keyboard .keyboard-bg .keylabels-ibmpc-alt {
	 width: 56px; height: 42px; padding: 3px;
}

.keyboard .keyboard-bg .keyborder-macbook-std {
	 width: 48px; height: 48px; border-style: solid; border-width: 1px; border-color: black; border-radius: 4px; background-color: #cccccc;
}
.keyboard .keyboard-bg .keyborder-macbook-fkey {
	 width: 50px; height: 35px; border-style: solid; border-width: 1px; border-color: black; border-radius: 4px; background-color: #cccccc;
}
.keyboard .keyboard-bg .keyborder-macbook-cursorkey {
	  width: 48px; height: 27px; border-style: solid; border-width: 1px; border-color: black; border-radius: 4px; background-color: #cccccc;
}
.keyboard .keyboard-bg .keytop-macbook-std {
	 width: 46px; height: 44px; border-style: solid; border-width: 1px; border-color: rgba(0,0,0,0.1); background-color: #fcfcfc; border-radius: 4px;
}
.keyboard .keyboard-bg .keytop-macbook-fkey {
	 width: 48px; height: 31px; border-style: solid; border-width: 1px; border-color: rgba(0,0,0,0.1); background-color: #fcfcfc; border-radius: 4px;
}
.keyboard .keyboard-bg .keytop-macbook-cursorkey {
	  width: 46px; height: 23px; border-style: solid; border-width: 1px; border-color: rgba(0,0,0,0.1); background-color: #fcfcfc; border-radius: 4px;
}
.keyboard .keyboard-bg .keylabels-macbook-std {
	 width: 46px; height: 44px; padding: 4px;
}
.keyboard .keyboard-bg .keylabels-macbook-fkey {
	 width: 48px; height: 31px; padding: 4px;
}
.keyboard .keyboard-bg .keylabels-macbook-cursorkey {
	  width: 46px; height: 23px; padding: 4px;
}
.keylabel-macbook-std {
	 color:#7c7c7c; width:38px; height:36px;
}
.keylabel-macbook-fkey {
	 color:#7c7c7c; width:40px; height:23px;
}
.keylabel-macbook-cursorkey {
	 color:#7c7c7c; width:38px; height:15px;
}

.keylabel-ibmpc-std {
	 color:#080808; width:36px; height:36px;
}
.keylabel-ibmpc-alt {
	 color:#080808; width:50px; height:36px;
}

.keyboard-std-keylabel {
  width:36px;
  max-width:36px;
  height:36px;
}
.keyboard-alt-keylabel {
	 width:50px; max-width:50px; height:36px;
}

.keyboard-std-keylabel2 {
  width:38px;
  max-width:38px;
  height:36px;
}

.keyboard-macbook-keylabel-fkey {
	 width:40px; max-width:40px; height:23px;
}
.keyboard-macbook-keylabel-cursorkey {
	  width:38px; max-width:38px; height:15px;
}

.keyboard-bg-macbook {
    background-image: linear-gradient(to bottom, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 4%, rgba(255,255,255,0.3) 6%, rgba(0,0,0,0) 10%), linear-gradient(to right, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0) 100%) !important;
}
.keyboard .keycap .keylabel {
    font-family: varela_round_regular; /* , volkswagen_serialregular */
}


text:
package at.kc.tugraz.ss.serv.rating.conf;

import at.tugraz.sss.serv.conf.api.SSServConfA;

public class SSRatingConf extends SSServConfA{

  public static SSRatingConf copy(final SSRatingConf orig){

    final SSRatingConf copy = (SSRatingConf) SSServConfA.copy(orig, new SSRatingConf());

    return copy;
  }
}


text:
class CPHSplitedShell : public CPHShell {
    float m_max_AABBradius;
    virtual void SetMaxAABBRadius(float size) { m_max_AABBradius = size; }

protected:
    virtual void Collide();
    virtual void get_spatial_params();
    virtual void DisableObject();

private:
public:
    CPHSplitedShell() { m_max_AABBradius = dInfinity; }
};

#endif


text:
title: "SaltStack integration"
linkTitle: "SaltStack"
description: "Use the Sensu SaltStack Handler integration to launch SaltStack functions for automated remediation based on Sensu observability event data."
version: "6.5"
product: "Sensu Go"
menu:
  sensu-go-6.5:
    parent: featured-integrations
---

{{% notice commercial %}}
**COMMERCIAL FEATURE**: Access the Sensu SaltStack Handler integration in the packaged Sensu Go distribution.
For more information, read [Get started with commercial features](../../../commercial/).
{{% /notice %}}

The [Sensu SaltStack Handler plugin][4] is a Sensu [handler][1] that launches SaltStack functions for automated remediation based on Sensu event data.

{{% notice note %}}
**NOTE**: The Sensu SaltStack Handler plugin is an example of Sensu's auto-remediation integrations.
To find more integrations, search [Bonsai, the Sensu asset hub](https://bonsai.sensu.io/).
{{% /notice %}}

## Features

The [Sensu SaltStack Handler plugin][4] supports both SaltStack Enterprise and SaltStack Open Source as well as SaltStack functions such as `service`, `state`, `saltutil`, and `grains` (including `arg` and `kwarg` arguments).

- Specify SaltStack functions and trigger parameters for remediation actions for a check with Sensu annotations.
- Use [event-based templating][2] to specify the minion to target for rememdiation based on event data.
- Keep your SaltStack username and password secure with Sensu [environment variables and secrets management][7].

## Get the plugin

For a turnkey experience with the Sensu SaltStack Handler plugin, use our curated, configurable [quick-start template][3] to integrate Sensu with your existing SaltStack workflows.

You can also add the [Sensu SaltStack Handler plugin][4] with a dynamic runtime asset from Bonsai, the Sensu asset hub, to build your own workflow or integrate Sensu with your existing SaltStack workflows.
[Dynamic runtime assets][5] are shareable, reusable packages that make it easier to deploy Sensu plugins.

[1]: ../../../observability-pipeline/observe-process/handlers/
[2]: ../../../observability-pipeline/observe-process/handler-templates/
[3]: https://github.com/sensu/catalog/blob/docs-archive/integrations/saltstack/saltstack-handler.yaml
[4]: https://bonsai.sensu.io/assets/sensu/sensu-saltstack-handler
[5]: ../../assets/
[7]: ../../../operations/manage-secrets/