diff --git a/assets/js/scrollreveal.js b/assets/js/scrollreveal.js new file mode 100644 index 00000000000..c2b2dcc5694 --- /dev/null +++ b/assets/js/scrollreveal.js @@ -0,0 +1,1546 @@ +/*! @license ScrollReveal v4.0.5 + + Copyright 2018 Fisssion LLC. + + Licensed under the GNU General Public License 3.0 for + compatible open source projects and non-commercial use. + + For commercial sites, themes, projects, and applications, + keep your source code private/proprietary by purchasing + a commercial license from https://scrollrevealjs.org/ +*/ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.ScrollReveal = factory()); +}(this, (function () { 'use strict'; + +var defaults = { + delay: 0, + distance: '0', + duration: 600, + easing: 'cubic-bezier(0.5, 0, 0, 1)', + interval: 0, + opacity: 0, + origin: 'bottom', + rotate: { + x: 0, + y: 0, + z: 0 + }, + scale: 1, + cleanup: false, + container: document.documentElement, + desktop: true, + mobile: true, + reset: false, + useDelay: 'always', + viewFactor: 0.0, + viewOffset: { + top: 0, + right: 0, + bottom: 0, + left: 0 + }, + afterReset: function afterReset() {}, + afterReveal: function afterReveal() {}, + beforeReset: function beforeReset() {}, + beforeReveal: function beforeReveal() {} +} + +function failure() { + document.documentElement.classList.remove('sr'); + + return { + clean: function clean() {}, + destroy: function destroy() {}, + reveal: function reveal() {}, + sync: function sync() {}, + get noop() { + return true + } + } +} + +function success() { + document.documentElement.classList.add('sr'); + + if (document.body) { + document.body.style.height = '100%'; + } else { + document.addEventListener('DOMContentLoaded', function () { + document.body.style.height = '100%'; + }); + } +} + +var mount = { success: success, failure: failure } + +/*! @license is-dom-node v1.0.4 + + Copyright 2018 Fisssion LLC. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +*/ +function isDomNode(x) { + return typeof window.Node === 'object' + ? x instanceof window.Node + : x !== null && + typeof x === 'object' && + typeof x.nodeType === 'number' && + typeof x.nodeName === 'string' +} + +/*! @license is-dom-node-list v1.2.1 + + Copyright 2018 Fisssion LLC. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +*/ +function isDomNodeList(x) { + var prototypeToString = Object.prototype.toString.call(x); + var regex = /^\[object (HTMLCollection|NodeList|Object)\]$/; + + return typeof window.NodeList === 'object' + ? x instanceof window.NodeList + : x !== null && + typeof x === 'object' && + typeof x.length === 'number' && + regex.test(prototypeToString) && + (x.length === 0 || isDomNode(x[0])) +} + +/*! @license Tealight v0.3.6 + + Copyright 2018 Fisssion LLC. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +*/ +function tealight(target, context) { + if ( context === void 0 ) { context = document; } + + if (target instanceof Array) { return target.filter(isDomNode); } + if (isDomNode(target)) { return [target]; } + if (isDomNodeList(target)) { return Array.prototype.slice.call(target); } + if (typeof target === "string") { + try { + var query = context.querySelectorAll(target); + return Array.prototype.slice.call(query); + } catch (err) { + return []; + } + } + return []; +} + +function isObject(x) { + return ( + x !== null && + x instanceof Object && + (x.constructor === Object || + Object.prototype.toString.call(x) === '[object Object]') + ) +} + +function each(collection, callback) { + if (isObject(collection)) { + var keys = Object.keys(collection); + return keys.forEach(function (key) { return callback(collection[key], key, collection); }) + } + if (collection instanceof Array) { + return collection.forEach(function (item, i) { return callback(item, i, collection); }) + } + throw new TypeError('Expected either an array or object literal.') +} + +function logger(message) { + var details = [], len = arguments.length - 1; + while ( len-- > 0 ) details[ len ] = arguments[ len + 1 ]; + + if (this.constructor.debug && console) { + var report = "%cScrollReveal: " + message; + details.forEach(function (detail) { return (report += "\n — " + detail); }); + console.log(report, 'color: #ea654b;'); // eslint-disable-line no-console + } +} + +function rinse() { + var this$1 = this; + + var struct = function () { return ({ + active: [], + stale: [] + }); }; + + var elementIds = struct(); + var sequenceIds = struct(); + var containerIds = struct(); + + /** + * Take stock of active element IDs. + */ + try { + each(tealight('[data-sr-id]'), function (node) { + var id = parseInt(node.getAttribute('data-sr-id')); + elementIds.active.push(id); + }); + } catch (e) { + throw e + } + /** + * Destroy stale elements. + */ + each(this.store.elements, function (element) { + if (elementIds.active.indexOf(element.id) === -1) { + elementIds.stale.push(element.id); + } + }); + + each(elementIds.stale, function (staleId) { return delete this$1.store.elements[staleId]; }); + + /** + * Take stock of active container and sequence IDs. + */ + each(this.store.elements, function (element) { + if (containerIds.active.indexOf(element.containerId) === -1) { + containerIds.active.push(element.containerId); + } + if (element.hasOwnProperty('sequence')) { + if (sequenceIds.active.indexOf(element.sequence.id) === -1) { + sequenceIds.active.push(element.sequence.id); + } + } + }); + + /** + * Destroy stale containers. + */ + each(this.store.containers, function (container) { + if (containerIds.active.indexOf(container.id) === -1) { + containerIds.stale.push(container.id); + } + }); + + each(containerIds.stale, function (staleId) { + var stale = this$1.store.containers[staleId].node; + stale.removeEventListener('scroll', this$1.delegate); + stale.removeEventListener('resize', this$1.delegate); + delete this$1.store.containers[staleId]; + }); + + /** + * Destroy stale sequences. + */ + each(this.store.sequences, function (sequence) { + if (sequenceIds.active.indexOf(sequence.id) === -1) { + sequenceIds.stale.push(sequence.id); + } + }); + + each(sequenceIds.stale, function (staleId) { return delete this$1.store.sequences[staleId]; }); +} + +function clean(target) { + var this$1 = this; + + var dirty; + try { + each(tealight(target), function (node) { + var id = node.getAttribute('data-sr-id'); + if (id !== null) { + dirty = true; + var element = this$1.store.elements[id]; + if (element.callbackTimer) { + window.clearTimeout(element.callbackTimer.clock); + } + node.setAttribute('style', element.styles.inline.generated); + node.removeAttribute('data-sr-id'); + delete this$1.store.elements[id]; + } + }); + } catch (e) { + return logger.call(this, 'Clean failed.', e.message) + } + + if (dirty) { + try { + rinse.call(this); + } catch (e) { + return logger.call(this, 'Clean failed.', e.message) + } + } +} + +function destroy() { + var this$1 = this; + + /** + * Remove all generated styles and element ids + */ + each(this.store.elements, function (element) { + element.node.setAttribute('style', element.styles.inline.generated); + element.node.removeAttribute('data-sr-id'); + }); + + /** + * Remove all event listeners. + */ + each(this.store.containers, function (container) { + var target = + container.node === document.documentElement ? window : container.node; + target.removeEventListener('scroll', this$1.delegate); + target.removeEventListener('resize', this$1.delegate); + }); + + /** + * Clear all data from the store + */ + this.store = { + containers: {}, + elements: {}, + history: [], + sequences: {} + }; +} + +/*! @license Rematrix v0.3.0 + + Copyright 2018 Julian Lloyd. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +/** + * @module Rematrix + */ + +/** + * Transformation matrices in the browser come in two flavors: + * + * - `matrix` using 6 values (short) + * - `matrix3d` using 16 values (long) + * + * This utility follows this [conversion guide](https://goo.gl/EJlUQ1) + * to expand short form matrices to their equivalent long form. + * + * @param {array} source - Accepts both short and long form matrices. + * @return {array} + */ +function format(source) { + if (source.constructor !== Array) { + throw new TypeError('Expected array.') + } + if (source.length === 16) { + return source + } + if (source.length === 6) { + var matrix = identity(); + matrix[0] = source[0]; + matrix[1] = source[1]; + matrix[4] = source[2]; + matrix[5] = source[3]; + matrix[12] = source[4]; + matrix[13] = source[5]; + return matrix + } + throw new RangeError('Expected array with either 6 or 16 values.') +} + +/** + * Returns a matrix representing no transformation. The product of any matrix + * multiplied by the identity matrix will be the original matrix. + * + * > **Tip:** Similar to how `5 * 1 === 5`, where `1` is the identity. + * + * @return {array} + */ +function identity() { + var matrix = []; + for (var i = 0; i < 16; i++) { + i % 5 == 0 ? matrix.push(1) : matrix.push(0); + } + return matrix +} + +/** + * Returns a 4x4 matrix describing the combined transformations + * of both arguments. + * + * > **Note:** Order is very important. For example, rotating 45° + * along the Z-axis, followed by translating 500 pixels along the + * Y-axis... is not the same as translating 500 pixels along the + * Y-axis, followed by rotating 45° along on the Z-axis. + * + * @param {array} m - Accepts both short and long form matrices. + * @param {array} x - Accepts both short and long form matrices. + * @return {array} + */ +function multiply(m, x) { + var fm = format(m); + var fx = format(x); + var product = []; + + for (var i = 0; i < 4; i++) { + var row = [fm[i], fm[i + 4], fm[i + 8], fm[i + 12]]; + for (var j = 0; j < 4; j++) { + var k = j * 4; + var col = [fx[k], fx[k + 1], fx[k + 2], fx[k + 3]]; + var result = + row[0] * col[0] + row[1] * col[1] + row[2] * col[2] + row[3] * col[3]; + + product[i + k] = result; + } + } + + return product +} + +/** + * Attempts to return a 4x4 matrix describing the CSS transform + * matrix passed in, but will return the identity matrix as a + * fallback. + * + * > **Tip:** This method is used to convert a CSS matrix (retrieved as a + * `string` from computed styles) to its equivalent array format. + * + * @param {string} source - `matrix` or `matrix3d` CSS Transform value. + * @return {array} + */ +function parse(source) { + if (typeof source === 'string') { + var match = source.match(/matrix(3d)?\(([^)]+)\)/); + if (match) { + var raw = match[2].split(', ').map(parseFloat); + return format(raw) + } + } + return identity() +} + +/** + * Returns a 4x4 matrix describing X-axis rotation. + * + * @param {number} angle - Measured in degrees. + * @return {array} + */ +function rotateX(angle) { + var theta = Math.PI / 180 * angle; + var matrix = identity(); + + matrix[5] = matrix[10] = Math.cos(theta); + matrix[6] = matrix[9] = Math.sin(theta); + matrix[9] *= -1; + + return matrix +} + +/** + * Returns a 4x4 matrix describing Y-axis rotation. + * + * @param {number} angle - Measured in degrees. + * @return {array} + */ +function rotateY(angle) { + var theta = Math.PI / 180 * angle; + var matrix = identity(); + + matrix[0] = matrix[10] = Math.cos(theta); + matrix[2] = matrix[8] = Math.sin(theta); + matrix[2] *= -1; + + return matrix +} + +/** + * Returns a 4x4 matrix describing Z-axis rotation. + * + * @param {number} angle - Measured in degrees. + * @return {array} + */ +function rotateZ(angle) { + var theta = Math.PI / 180 * angle; + var matrix = identity(); + + matrix[0] = matrix[5] = Math.cos(theta); + matrix[1] = matrix[4] = Math.sin(theta); + matrix[4] *= -1; + + return matrix +} + +/** + * Returns a 4x4 matrix describing 2D scaling. The first argument + * is used for both X and Y-axis scaling, unless an optional + * second argument is provided to explicitly define Y-axis scaling. + * + * @param {number} scalar - Decimal multiplier. + * @param {number} [scalarY] - Decimal multiplier. + * @return {array} + */ +function scale(scalar, scalarY) { + var matrix = identity(); + + matrix[0] = scalar; + matrix[5] = typeof scalarY === 'number' ? scalarY : scalar; + + return matrix +} + +/** + * Returns a 4x4 matrix describing X-axis translation. + * + * @param {number} distance - Measured in pixels. + * @return {array} + */ +function translateX(distance) { + var matrix = identity(); + matrix[12] = distance; + return matrix +} + +/** + * Returns a 4x4 matrix describing Y-axis translation. + * + * @param {number} distance - Measured in pixels. + * @return {array} + */ +function translateY(distance) { + var matrix = identity(); + matrix[13] = distance; + return matrix +} + +var getPrefixedCssProp = (function () { + var properties = {}; + var style = document.documentElement.style; + + function getPrefixedCssProperty(name, source) { + if ( source === void 0 ) source = style; + + if (name && typeof name === 'string') { + if (properties[name]) { + return properties[name] + } + if (typeof source[name] === 'string') { + return (properties[name] = name) + } + if (typeof source[("-webkit-" + name)] === 'string') { + return (properties[name] = "-webkit-" + name) + } + throw new RangeError(("Unable to find \"" + name + "\" style property.")) + } + throw new TypeError('Expected a string.') + } + + getPrefixedCssProperty.clearCache = function () { return (properties = {}); }; + + return getPrefixedCssProperty +})(); + +function style(element) { + var computed = window.getComputedStyle(element.node); + var position = computed.position; + var config = element.config; + + /** + * Generate inline styles + */ + var inline = {}; + var inlineStyle = element.node.getAttribute('style') || ''; + var inlineMatch = inlineStyle.match(/[\w-]+\s*:\s*[^;]+\s*/gi) || []; + + inline.computed = inlineMatch ? inlineMatch.map(function (m) { return m.trim(); }).join('; ') + ';' : ''; + + inline.generated = inlineMatch.some(function (m) { return m.match(/visibility\s?:\s?visible/i); }) + ? inline.computed + : inlineMatch.concat( ['visibility: visible']).map(function (m) { return m.trim(); }).join('; ') + ';'; + + /** + * Generate opacity styles + */ + var computedOpacity = parseFloat(computed.opacity); + var configOpacity = !isNaN(parseFloat(config.opacity)) + ? parseFloat(config.opacity) + : parseFloat(computed.opacity); + + var opacity = { + computed: computedOpacity !== configOpacity ? ("opacity: " + computedOpacity + ";") : '', + generated: computedOpacity !== configOpacity ? ("opacity: " + configOpacity + ";") : '' + }; + + /** + * Generate transformation styles + */ + var transformations = []; + + if (parseFloat(config.distance)) { + var axis = config.origin === 'top' || config.origin === 'bottom' ? 'Y' : 'X'; + + /** + * Let’s make sure our our pixel distances are negative for top and left. + * e.g. { origin: 'top', distance: '25px' } starts at `top: -25px` in CSS. + */ + var distance = config.distance; + if (config.origin === 'top' || config.origin === 'left') { + distance = /^-/.test(distance) ? distance.substr(1) : ("-" + distance); + } + + var ref = distance.match(/(^-?\d+\.?\d?)|(em$|px$|%$)/g); + var value = ref[0]; + var unit = ref[1]; + + switch (unit) { + case 'em': + distance = parseInt(computed.fontSize) * value; + break + case 'px': + distance = value; + break + case '%': + /** + * Here we use `getBoundingClientRect` instead of + * the existing data attached to `element.geometry` + * because only the former includes any transformations + * current applied to the element. + * + * If that behavior ends up being unintuitive, this + * logic could instead utilize `element.geometry.height` + * and `element.geoemetry.width` for the distaince calculation + */ + distance = + axis === 'Y' + ? element.node.getBoundingClientRect().height * value / 100 + : element.node.getBoundingClientRect().width * value / 100; + break + default: + throw new RangeError('Unrecognized or missing distance unit.') + } + + if (axis === 'Y') { + transformations.push(translateY(distance)); + } else { + transformations.push(translateX(distance)); + } + } + + if (config.rotate.x) { transformations.push(rotateX(config.rotate.x)); } + if (config.rotate.y) { transformations.push(rotateY(config.rotate.y)); } + if (config.rotate.z) { transformations.push(rotateZ(config.rotate.z)); } + if (config.scale !== 1) { + if (config.scale === 0) { + /** + * The CSS Transforms matrix interpolation specification + * basically disallows transitions of non-invertible + * matrixes, which means browsers won't transition + * elements with zero scale. + * + * That’s inconvenient for the API and developer + * experience, so we simply nudge their value + * slightly above zero; this allows browsers + * to transition our element as expected. + * + * `0.0002` was the smallest number + * that performed across browsers. + */ + transformations.push(scale(0.0002)); + } else { + transformations.push(scale(config.scale)); + } + } + + var transform = {}; + if (transformations.length) { + transform.property = getPrefixedCssProp('transform'); + /** + * The default computed transform value should be one of: + * undefined || 'none' || 'matrix()' || 'matrix3d()' + */ + transform.computed = { + raw: computed[transform.property], + matrix: parse(computed[transform.property]) + }; + + transformations.unshift(transform.computed.matrix); + var product = transformations.reduce(multiply); + + transform.generated = { + initial: ((transform.property) + ": matrix3d(" + (product.join(', ')) + ");"), + final: ((transform.property) + ": matrix3d(" + (transform.computed.matrix.join( + ', ' + )) + ");") + }; + } else { + transform.generated = { + initial: '', + final: '' + }; + } + + /** + * Generate transition styles + */ + var transition = {}; + if (opacity.generated || transform.generated.initial) { + transition.property = getPrefixedCssProp('transition'); + transition.computed = computed[transition.property]; + transition.fragments = []; + + var delay = config.delay; + var duration = config.duration; + var easing = config.easing; + + if (opacity.generated) { + transition.fragments.push({ + delayed: ("opacity " + (duration / 1000) + "s " + easing + " " + (delay / 1000) + "s"), + instant: ("opacity " + (duration / 1000) + "s " + easing + " 0s") + }); + } + + if (transform.generated.initial) { + transition.fragments.push({ + delayed: ((transform.property) + " " + (duration / 1000) + "s " + easing + " " + (delay / + 1000) + "s"), + instant: ((transform.property) + " " + (duration / 1000) + "s " + easing + " 0s") + }); + } + + /** + * The default computed transition property should be one of: + * undefined || '' || 'all 0s ease 0s' || 'all 0s 0s cubic-bezier()' + */ + if (transition.computed && !transition.computed.match(/all 0s/)) { + transition.fragments.unshift({ + delayed: transition.computed, + instant: transition.computed + }); + } + + var composed = transition.fragments.reduce( + function (composition, fragment, i) { + composition.delayed += + i === 0 ? fragment.delayed : (", " + (fragment.delayed)); + composition.instant += + i === 0 ? fragment.instant : (", " + (fragment.instant)); + return composition + }, + { + delayed: '', + instant: '' + } + ); + + transition.generated = { + delayed: ((transition.property) + ": " + (composed.delayed) + ";"), + instant: ((transition.property) + ": " + (composed.instant) + ";") + }; + } else { + transition.generated = { + delayed: '', + instant: '' + }; + } + + return { + inline: inline, + opacity: opacity, + position: position, + transform: transform, + transition: transition + } +} + +function animate(element, force) { + if ( force === void 0 ) force = {}; + + var pristine = force.pristine || this.pristine; + var delayed = + element.config.useDelay === 'always' || + (element.config.useDelay === 'onload' && pristine) || + (element.config.useDelay === 'once' && !element.seen); + + var shouldReveal = element.visible && !element.revealed; + var shouldReset = !element.visible && element.revealed && element.config.reset; + + if (force.reveal || shouldReveal) { + return triggerReveal.call(this, element, delayed) + } + + if (force.reset || shouldReset) { + return triggerReset.call(this, element) + } +} + +function triggerReveal(element, delayed) { + var styles = [ + element.styles.inline.generated, + element.styles.opacity.computed, + element.styles.transform.generated.final + ]; + if (delayed) { + styles.push(element.styles.transition.generated.delayed); + } else { + styles.push(element.styles.transition.generated.instant); + } + element.revealed = element.seen = true; + element.node.setAttribute('style', styles.filter(function (s) { return s !== ''; }).join(' ')); + registerCallbacks.call(this, element, delayed); +} + +function triggerReset(element) { + var styles = [ + element.styles.inline.generated, + element.styles.opacity.generated, + element.styles.transform.generated.initial, + element.styles.transition.generated.instant + ]; + element.revealed = false; + element.node.setAttribute('style', styles.filter(function (s) { return s !== ''; }).join(' ')); + registerCallbacks.call(this, element); +} + +function registerCallbacks(element, isDelayed) { + var this$1 = this; + + var duration = isDelayed + ? element.config.duration + element.config.delay + : element.config.duration; + + var beforeCallback = element.revealed + ? element.config.beforeReveal + : element.config.beforeReset; + + var afterCallback = element.revealed + ? element.config.afterReveal + : element.config.afterReset; + + var elapsed = 0; + if (element.callbackTimer) { + elapsed = Date.now() - element.callbackTimer.start; + window.clearTimeout(element.callbackTimer.clock); + } + + beforeCallback(element.node); + + element.callbackTimer = { + start: Date.now(), + clock: window.setTimeout(function () { + afterCallback(element.node); + element.callbackTimer = null; + if (element.revealed && !element.config.reset && element.config.cleanup) { + clean.call(this$1, element.node); + } + }, duration - elapsed) + }; +} + +var nextUniqueId = (function () { + var uid = 0; + return function () { return uid++; } +})(); + +function sequence(element, pristine) { + if ( pristine === void 0 ) pristine = this.pristine; + + /** + * We first check if the element should reset. + */ + if (!element.visible && element.revealed && element.config.reset) { + return animate.call(this, element, { reset: true }) + } + + var seq = this.store.sequences[element.sequence.id]; + var i = element.sequence.index; + + if (seq) { + var visible = new SequenceModel(seq, 'visible', this.store); + var revealed = new SequenceModel(seq, 'revealed', this.store); + + seq.models = { visible: visible, revealed: revealed }; + + /** + * If the sequence has no revealed members, + * then we reveal the first visible element + * within that sequence. + * + * The sequence then cues a recursive call + * in both directions. + */ + if (!revealed.body.length) { + var nextId = seq.members[visible.body[0]]; + var nextElement = this.store.elements[nextId]; + + if (nextElement) { + cue.call(this, seq, visible.body[0], -1, pristine); + cue.call(this, seq, visible.body[0], +1, pristine); + return animate.call(this, nextElement, { reveal: true, pristine: pristine }) + } + } + + /** + * If our element isn’t resetting, we check the + * element sequence index against the head, and + * then the foot of the sequence. + */ + if ( + !seq.blocked.head && + i === [].concat( revealed.head ).pop() && + i >= [].concat( visible.body ).shift() + ) { + cue.call(this, seq, i, -1, pristine); + return animate.call(this, element, { reveal: true, pristine: pristine }) + } + + if ( + !seq.blocked.foot && + i === [].concat( revealed.foot ).shift() && + i <= [].concat( visible.body ).pop() + ) { + cue.call(this, seq, i, +1, pristine); + return animate.call(this, element, { reveal: true, pristine: pristine }) + } + } +} + +function Sequence(interval) { + var i = Math.abs(interval); + if (!isNaN(i)) { + this.id = nextUniqueId(); + this.interval = Math.max(i, 16); + this.members = []; + this.models = {}; + this.blocked = { + head: false, + foot: false + }; + } else { + throw new RangeError('Invalid sequence interval.') + } +} + +function SequenceModel(seq, prop, store) { + var this$1 = this; + + this.head = []; + this.body = []; + this.foot = []; + + each(seq.members, function (id, index) { + var element = store.elements[id]; + if (element && element[prop]) { + this$1.body.push(index); + } + }); + + if (this.body.length) { + each(seq.members, function (id, index) { + var element = store.elements[id]; + if (element && !element[prop]) { + if (index < this$1.body[0]) { + this$1.head.push(index); + } else { + this$1.foot.push(index); + } + } + }); + } +} + +function cue(seq, i, direction, pristine) { + var this$1 = this; + + var blocked = ['head', null, 'foot'][1 + direction]; + var nextId = seq.members[i + direction]; + var nextElement = this.store.elements[nextId]; + + seq.blocked[blocked] = true; + + setTimeout(function () { + seq.blocked[blocked] = false; + if (nextElement) { + sequence.call(this$1, nextElement, pristine); + } + }, seq.interval); +} + +function initialize() { + var this$1 = this; + + rinse.call(this); + + each(this.store.elements, function (element) { + var styles = [element.styles.inline.generated]; + + if (element.visible) { + styles.push(element.styles.opacity.computed); + styles.push(element.styles.transform.generated.final); + element.revealed = true; + } else { + styles.push(element.styles.opacity.generated); + styles.push(element.styles.transform.generated.initial); + element.revealed = false; + } + + element.node.setAttribute('style', styles.filter(function (s) { return s !== ''; }).join(' ')); + }); + + each(this.store.containers, function (container) { + var target = + container.node === document.documentElement ? window : container.node; + target.addEventListener('scroll', this$1.delegate); + target.addEventListener('resize', this$1.delegate); + }); + + /** + * Manually invoke delegate once to capture + * element and container dimensions, container + * scroll position, and trigger any valid reveals + */ + this.delegate(); + + /** + * Wipe any existing `setTimeout` now + * that initialization has completed. + */ + this.initTimeout = null; +} + +function isMobile(agent) { + if ( agent === void 0 ) agent = navigator.userAgent; + + return /Android|iPhone|iPad|iPod/i.test(agent) +} + +function deepAssign(target) { + var sources = [], len = arguments.length - 1; + while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; + + if (isObject(target)) { + each(sources, function (source) { + each(source, function (data, key) { + if (isObject(data)) { + if (!target[key] || !isObject(target[key])) { + target[key] = {}; + } + deepAssign(target[key], data); + } else { + target[key] = data; + } + }); + }); + return target + } else { + throw new TypeError('Target must be an object literal.') + } +} + +function reveal(target, options, syncing) { + var this$1 = this; + if ( options === void 0 ) options = {}; + if ( syncing === void 0 ) syncing = false; + + var containerBuffer = []; + var sequence$$1; + var interval = options.interval || defaults.interval; + + try { + if (interval) { + sequence$$1 = new Sequence(interval); + } + + var nodes = tealight(target); + if (!nodes.length) { + throw new Error('Invalid reveal target.') + } + + var elements = nodes.reduce(function (elementBuffer, elementNode) { + var element = {}; + var existingId = elementNode.getAttribute('data-sr-id'); + + if (existingId) { + deepAssign(element, this$1.store.elements[existingId]); + + /** + * In order to prevent previously generated styles + * from throwing off the new styles, the style tag + * has to be reverted to its pre-reveal state. + */ + element.node.setAttribute('style', element.styles.inline.computed); + } else { + element.id = nextUniqueId(); + element.node = elementNode; + element.seen = false; + element.revealed = false; + element.visible = false; + } + + var config = deepAssign({}, element.config || this$1.defaults, options); + + if ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) { + if (existingId) { + clean.call(this$1, element); + } + return elementBuffer // skip elements that are disabled + } + + var containerNode = tealight(config.container)[0]; + if (!containerNode) { + throw new Error('Invalid container.') + } + if (!containerNode.contains(elementNode)) { + return elementBuffer // skip elements found outside the container + } + + var containerId; + { + containerId = getContainerId( + containerNode, + containerBuffer, + this$1.store.containers + ); + if (containerId === null) { + containerId = nextUniqueId(); + containerBuffer.push({ id: containerId, node: containerNode }); + } + } + + element.config = config; + element.containerId = containerId; + element.styles = style(element); + + if (sequence$$1) { + element.sequence = { + id: sequence$$1.id, + index: sequence$$1.members.length + }; + sequence$$1.members.push(element.id); + } + + elementBuffer.push(element); + return elementBuffer + }, []); + + /** + * Modifying the DOM via setAttribute needs to be handled + * separately from reading computed styles in the map above + * for the browser to batch DOM changes (limiting reflows) + */ + each(elements, function (element) { + this$1.store.elements[element.id] = element; + element.node.setAttribute('data-sr-id', element.id); + }); + } catch (e) { + return logger.call(this, 'Reveal failed.', e.message) + } + + /** + * Now that element set-up is complete... + * Let’s commit any container and sequence data we have to the store. + */ + each(containerBuffer, function (container) { + this$1.store.containers[container.id] = { + id: container.id, + node: container.node + }; + }); + if (sequence$$1) { + this.store.sequences[sequence$$1.id] = sequence$$1; + } + + /** + * If reveal wasn't invoked by sync, we want to + * make sure to add this call to the history. + */ + if (syncing !== true) { + this.store.history.push({ target: target, options: options }); + + /** + * Push initialization to the event queue, giving + * multiple reveal calls time to be interpreted. + */ + if (this.initTimeout) { + window.clearTimeout(this.initTimeout); + } + this.initTimeout = window.setTimeout(initialize.bind(this), 0); + } +} + +function getContainerId(node) { + var collections = [], len = arguments.length - 1; + while ( len-- > 0 ) collections[ len ] = arguments[ len + 1 ]; + + var id = null; + each(collections, function (collection) { + each(collection, function (container) { + if (id === null && container.node === node) { + id = container.id; + } + }); + }); + return id +} + +/** + * Re-runs the reveal method for each record stored in history, + * for capturing new content asynchronously loaded into the DOM. + */ +function sync() { + var this$1 = this; + + each(this.store.history, function (record) { + reveal.call(this$1, record.target, record.options, true); + }); + + initialize.call(this); +} + +var polyfill = function (x) { return (x > 0) - (x < 0) || +x; }; +var mathSign = Math.sign || polyfill + +/*! @license miniraf v1.0.0 + + Copyright 2018 Fisssion LLC. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +*/ +var polyfill$1 = (function () { + var clock = Date.now(); + + return function (callback) { + var currentTime = Date.now(); + if (currentTime - clock > 16) { + clock = currentTime; + callback(currentTime); + } else { + setTimeout(function () { return polyfill$1(callback); }, 0); + } + } +})(); + +var index = window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + polyfill$1; + +function getGeometry(target, isContainer) { + /** + * We want to ignore padding and scrollbars for container elements. + * More information here: https://goo.gl/vOZpbz + */ + var height = isContainer ? target.node.clientHeight : target.node.offsetHeight; + var width = isContainer ? target.node.clientWidth : target.node.offsetWidth; + + var offsetTop = 0; + var offsetLeft = 0; + var node = target.node; + + do { + if (!isNaN(node.offsetTop)) { + offsetTop += node.offsetTop; + } + if (!isNaN(node.offsetLeft)) { + offsetLeft += node.offsetLeft; + } + node = node.offsetParent; + } while (node) + + return { + bounds: { + top: offsetTop, + right: offsetLeft + width, + bottom: offsetTop + height, + left: offsetLeft + }, + height: height, + width: width + } +} + +function getScrolled(container) { + var top, left; + if (container.node === document.documentElement) { + top = window.pageYOffset; + left = window.pageXOffset; + } else { + top = container.node.scrollTop; + left = container.node.scrollLeft; + } + return { top: top, left: left } +} + +function isElementVisible(element) { + if ( element === void 0 ) element = {}; + + var container = this.store.containers[element.containerId]; + if (!container) { return } + + var viewFactor = Math.max(0, Math.min(1, element.config.viewFactor)); + var viewOffset = element.config.viewOffset; + + var elementBounds = { + top: element.geometry.bounds.top + element.geometry.height * viewFactor, + right: element.geometry.bounds.right - element.geometry.width * viewFactor, + bottom: element.geometry.bounds.bottom - element.geometry.height * viewFactor, + left: element.geometry.bounds.left + element.geometry.width * viewFactor + }; + + var containerBounds = { + top: container.geometry.bounds.top + container.scroll.top + viewOffset.top, + right: container.geometry.bounds.right + container.scroll.left - viewOffset.right, + bottom: + container.geometry.bounds.bottom + container.scroll.top - viewOffset.bottom, + left: container.geometry.bounds.left + container.scroll.left + viewOffset.left + }; + + return ( + (elementBounds.top < containerBounds.bottom && + elementBounds.right > containerBounds.left && + elementBounds.bottom > containerBounds.top && + elementBounds.left < containerBounds.right) || + element.styles.position === 'fixed' + ) +} + +function delegate( + event, + elements +) { + var this$1 = this; + if ( event === void 0 ) event = { type: 'init' }; + if ( elements === void 0 ) elements = this.store.elements; + + index(function () { + var stale = event.type === 'init' || event.type === 'resize'; + + each(this$1.store.containers, function (container) { + if (stale) { + container.geometry = getGeometry.call(this$1, container, true); + } + var scroll = getScrolled.call(this$1, container); + if (container.scroll) { + container.direction = { + x: mathSign(scroll.left - container.scroll.left), + y: mathSign(scroll.top - container.scroll.top) + }; + } + container.scroll = scroll; + }); + + /** + * Due to how the sequencer is implemented, it’s + * important that we update the state of all + * elements, before any animation logic is + * evaluated (in the second loop below). + */ + each(elements, function (element) { + if (stale) { + element.geometry = getGeometry.call(this$1, element); + } + element.visible = isElementVisible.call(this$1, element); + }); + + each(elements, function (element) { + if (element.sequence) { + sequence.call(this$1, element); + } else { + animate.call(this$1, element); + } + }); + + this$1.pristine = false; + }); +} + +function transformSupported() { + var style = document.documentElement.style; + return 'transform' in style || 'WebkitTransform' in style +} + +function transitionSupported() { + var style = document.documentElement.style; + return 'transition' in style || 'WebkitTransition' in style +} + +var version = "4.0.5"; + +var boundDelegate; +var boundDestroy; +var boundReveal; +var boundClean; +var boundSync; +var config; +var debug; +var instance; + +function ScrollReveal(options) { + if ( options === void 0 ) options = {}; + + var invokedWithoutNew = + typeof this === 'undefined' || + Object.getPrototypeOf(this) !== ScrollReveal.prototype; + + if (invokedWithoutNew) { + return new ScrollReveal(options) + } + + if (!ScrollReveal.isSupported()) { + logger.call(this, 'Instantiation failed.', 'This browser is not supported.'); + return mount.failure() + } + + var buffer; + try { + buffer = config + ? deepAssign({}, config, options) + : deepAssign({}, defaults, options); + } catch (e) { + logger.call(this, 'Invalid configuration.', e.message); + return mount.failure() + } + + try { + var container = tealight(buffer.container)[0]; + if (!container) { + throw new Error('Invalid container.') + } + } catch (e) { + logger.call(this, e.message); + return mount.failure() + } + + config = buffer; + + if ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) { + logger.call( + this, + 'This device is disabled.', + ("desktop: " + (config.desktop)), + ("mobile: " + (config.mobile)) + ); + return mount.failure() + } + + mount.success(); + + this.store = { + containers: {}, + elements: {}, + history: [], + sequences: {} + }; + + this.pristine = true; + + boundDelegate = boundDelegate || delegate.bind(this); + boundDestroy = boundDestroy || destroy.bind(this); + boundReveal = boundReveal || reveal.bind(this); + boundClean = boundClean || clean.bind(this); + boundSync = boundSync || sync.bind(this); + + Object.defineProperty(this, 'delegate', { get: function () { return boundDelegate; } }); + Object.defineProperty(this, 'destroy', { get: function () { return boundDestroy; } }); + Object.defineProperty(this, 'reveal', { get: function () { return boundReveal; } }); + Object.defineProperty(this, 'clean', { get: function () { return boundClean; } }); + Object.defineProperty(this, 'sync', { get: function () { return boundSync; } }); + + Object.defineProperty(this, 'defaults', { get: function () { return config; } }); + Object.defineProperty(this, 'version', { get: function () { return version; } }); + Object.defineProperty(this, 'noop', { get: function () { return false; } }); + + return instance ? instance : (instance = this) +} + +ScrollReveal.isSupported = function () { return transformSupported() && transitionSupported(); }; + +Object.defineProperty(ScrollReveal, 'debug', { + get: function () { return debug || false; }, + set: function (value) { return (debug = typeof value === 'boolean' ? value : debug); } +}); + +ScrollReveal(); + +return ScrollReveal; + +}))); diff --git a/assets/js/vendors.js b/assets/js/vendors.js new file mode 100644 index 00000000000..5993703b755 --- /dev/null +++ b/assets/js/vendors.js @@ -0,0 +1,33 @@ +/*! @license ScrollReveal v4.0.5 + + Copyright 2018 Fisssion LLC. + + Licensed under the GNU General Public License 3.0 for + compatible open source projects and non-commercial use. + + For commercial sites, themes, projects, and applications, + keep your source code private/proprietary by purchasing + a commercial license from https://scrollrevealjs.org/ +*/ +var ScrollReveal=function(){"use strict";var r={delay:0,distance:"0",duration:600,easing:"cubic-bezier(0.5, 0, 0, 1)",interval:0,opacity:0,origin:"bottom",rotate:{x:0,y:0,z:0},scale:1,cleanup:!1,container:document.documentElement,desktop:!0,mobile:!0,reset:!1,useDelay:"always",viewFactor:0,viewOffset:{top:0,right:0,bottom:0,left:0},afterReset:function(){},afterReveal:function(){},beforeReset:function(){},beforeReveal:function(){}};var n={success:function(){document.documentElement.classList.add("sr"),document.body?document.body.style.height="100%":document.addEventListener("DOMContentLoaded",function(){document.body.style.height="100%"})},failure:function(){return document.documentElement.classList.remove("sr"),{clean:function(){},destroy:function(){},reveal:function(){},sync:function(){},get noop(){return!0}}}};function o(e){return"object"==typeof window.Node?e instanceof window.Node:null!==e&&"object"==typeof e&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName}function u(e,t){if(void 0===t&&(t=document),e instanceof Array)return e.filter(o);if(o(e))return[e];if(n=e,i=Object.prototype.toString.call(n),"object"==typeof window.NodeList?n instanceof window.NodeList:null!==n&&"object"==typeof n&&"number"==typeof n.length&&/^\[object (HTMLCollection|NodeList|Object)\]$/.test(i)&&(0===n.length||o(n[0])))return Array.prototype.slice.call(e);var n,i;if("string"==typeof e)try{var r=t.querySelectorAll(e);return Array.prototype.slice.call(r)}catch(e){return[]}return[]}function s(e){return null!==e&&e instanceof Object&&(e.constructor===Object||"[object Object]"===Object.prototype.toString.call(e))}function f(n,i){if(s(n))return Object.keys(n).forEach(function(e){return i(n[e],e,n)});if(n instanceof Array)return n.forEach(function(e,t){return i(e,t,n)});throw new TypeError("Expected either an array or object literal.")}function h(e){for(var t=[],n=arguments.length-1;0=[].concat(r.body).shift())return g.call(this,n,i,-1,t),c.call(this,e,{reveal:!0,pristine:t});if(!n.blocked.foot&&i===[].concat(o.foot).shift()&&i<=[].concat(r.body).pop())return g.call(this,n,i,1,t),c.call(this,e,{reveal:!0,pristine:t})}}function v(e){var t=Math.abs(e);if(isNaN(t))throw new RangeError("Invalid sequence interval.");this.id=y(),this.interval=Math.max(t,16),this.members=[],this.models={},this.blocked={head:!1,foot:!1}}function d(e,i,r){var o=this;this.head=[],this.body=[],this.foot=[],f(e.members,function(e,t){var n=r.elements[e];n&&n[i]&&o.body.push(t)}),this.body.length&&f(e.members,function(e,t){var n=r.elements[e];n&&!n[i]&&(tPrevious',nextArrow:'',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(e,t){return i(' + + +
+
+
+
+
+
+
+ +
+
+
+
+
+

+ 2.x + Rancher 2.x +

+ +
+ +

Rancher manages all of your Kubernetes clusters everywhere, unifies them under centralized RBAC, monitors them and lets you easily deploy and manage workloads through an intuitive user interface.

+ + +
+
+
+
+

+ 1.6 + Rancher 1.6 +

+ +
+ +

If you haven't yet migrated to Rancher 2.x, you can still find documentation for 1.6 here. This is only for legacy users of the 1.6 product.

+ + +
+
+
+
+

+ OS + RancherOS +

+ +
+ +

RancherOS is the lightest, easiest way to run Docker in production. Engineered from the ground up for security and speed, it runs all system services and user workloads within Docker containers.

+ + +
+
+
+
+

+ RKE + Rancher Kubernetes Engine +

+ +
+ +

Rancher Kubernetes Engine (RKE) is an extremely simple, lightning fast Kubernetes installer that works everywhere.

+ + +
+
+
+
+
+
+
+ diff --git a/content/os/v1.x/en/installation/configuration/private-registries/_index.md b/content/os/v1.x/en/installation/configuration/private-registries/_index.md index 65ebd182839..5abe0adbbaf 100644 --- a/content/os/v1.x/en/installation/configuration/private-registries/_index.md +++ b/content/os/v1.x/en/installation/configuration/private-registries/_index.md @@ -15,7 +15,7 @@ rancher: auth: dXNlcm5hbWU6cGFzc3dvcmQ= ``` -The `auth` key is generated by base64 encoding a string of the form `username:password`. The `docker login` command can be be used to generate an `auth` key. After running the command and authenticating successfully, the key can be found in the `$HOME/.docker/config.json` file. +The `auth` key is generated by base64 encoding a string of the form `username:password`. The `docker login` command can be used to generate an `auth` key. After running the command and authenticating successfully, the key can be found in the `$HOME/.docker/config.json` file. ```json { diff --git a/content/rancher/v2.x/en/admin-settings/authentication/ad/_index.md b/content/rancher/v2.x/en/admin-settings/authentication/ad/_index.md index a65ebc1b138..037a2fc6881 100644 --- a/content/rancher/v2.x/en/admin-settings/authentication/ad/_index.md +++ b/content/rancher/v2.x/en/admin-settings/authentication/ad/_index.md @@ -144,7 +144,7 @@ $ ldapsearch -x -D "acme\jdoe" -w "secret" -p 389 \ -h ad.acme.com -b "dc=acme,dc=com" -s sub "sAMAccountName=jdoe" ``` -This command performs an LDAP search with the search base set to the domain root (`-b "dc=acme,dc=com"`) and a filter targeting the the user account (`sAMAccountNam=jdoe`), returning the attributes for said user: +This command performs an LDAP search with the search base set to the domain root (`-b "dc=acme,dc=com"`) and a filter targeting the user account (`sAMAccountNam=jdoe`), returning the attributes for said user: ![LDAP User]({{< baseurl >}}/img/rancher/ldapsearch-user.png) diff --git a/content/rancher/v2.x/en/admin-settings/rbac/_index.md b/content/rancher/v2.x/en/admin-settings/rbac/_index.md index f3aedf6b0d6..d860a62995f 100644 --- a/content/rancher/v2.x/en/admin-settings/rbac/_index.md +++ b/content/rancher/v2.x/en/admin-settings/rbac/_index.md @@ -11,7 +11,7 @@ After you configure external authentication, the users that display on the **Use - If you are logged in as a local user, only local users display. -- If you are logged in an an external user, both external and local users display. +- If you are logged in an external user, both external and local users display. ## Users and Roles diff --git a/content/rancher/v2.x/en/backups/backups/ha-backups/_index.md b/content/rancher/v2.x/en/backups/backups/ha-backups/_index.md index 0437530f6bd..a3301c1a154 100644 --- a/content/rancher/v2.x/en/backups/backups/ha-backups/_index.md +++ b/content/rancher/v2.x/en/backups/backups/ha-backups/_index.md @@ -3,7 +3,7 @@ title: Creating Backups—High Availability Installs weight: 50 aliases: - /rancher/v2.x/en/installation/after-installation/ha-backup-and-restoration/ - - /rancher/v2.x/en/installation/backups-and-restoration/ha-backup-and-restoration/ + - /rancher/v2.x/en/installation/backups-and-restoration/ha-backup-and-restoration/ --- This section describes how to create backups of your high-availability Rancher install. @@ -45,36 +45,51 @@ To take recurring snapshots, enable the `etcd-snapshot` service, which is a serv 1. Open `rancher-cluster.yml` with your favorite text editor. -2. Add the following code block to the bottom of the file: +2. Edit the code for the `etcd` service to enable recurring snapshots. As of RKE v0.2.0, snapshots can be saved in a S3 compatible backend. - ``` - services: - etcd: - snapshot: true # enables recurring etcd snapshots - creation: 6h0s # time increment between snapshots - retention: 24h # time increment before snapshot purge - ``` + _Using RKE v0.2.0+_ -3. Edit the code according to your requirements. + ``` + services: + etcd: + backup_config: + enabled: true # enables recurring etcd snapshots + interval_hours: 6 # time increment between snapshots + retention: 60 # time in days before snapshot purge + # Optional S3 + s3_backup_config: + access_key: "myaccesskey" + secret_key: "myaccesssecret" + bucket_name: "my-backup-bucket" + endpoint: "s3.eu-west-1.amazonaws.com" + region: "eu-west-1" + ``` + + _Using RKE v0.1.x_ + + ``` + services: + etcd: + snapshot: true # enables recurring etcd snapshots + creation: 6h0s # time increment between snapshots + retention: 24h # time increment before snapshot purge + ``` 4. Save and close `rancher-cluster.yml`. - 5. Open **Terminal** and change directory to the location of the RKE binary. Your `rancher-cluster.yml` file must reside in the same directory. - 6. Run the following command: ``` rke up --config rancher-cluster.yml ``` - -**Result:** RKE is configured to take recurring snapshots of `etcd` on all nodes running the `etcd` role. Snapshots are saved to the following directory: `/opt/rke/etcd-snapshots/`. +**Result:** RKE is configured to take recurring snapshots of `etcd` on all nodes running the `etcd` role. Snapshots are saved locally to the following directory: `/opt/rke/etcd-snapshots/`. If configured, the snapshots are also uploaded to your S3 compatible backend. #### Option B: One-Time Snapshots When you're about to upgrade Rancher or restore it to a previous snapshot, you should snapshot your live image so that you have a backup of `etcd` in its last known state. -**To Take a One-Time Snapshot:** +**To Take a One-Time Local Snapshot:** 1. Open **Terminal** and change directory to the location of the RKE binary. Your `rancher-cluster.yml` file must reside in the same directory. @@ -86,7 +101,25 @@ When you're about to upgrade Rancher or restore it to a previous snapshot, you s **Result:** RKE takes a snapshot of `etcd` running on each `etcd` node. The file is saved to `/opt/rke/etcd-snapshots`. -### 2. Backup Snapshots to a Safe Location +**To Take a One-Time S3 Snapshot:** + +_Available as of RKE v0.2.0_ + +1. Open **Terminal** and change directory to the location of the RKE binary. Your `rancher-cluster.yml` file must reside in the same directory. + +2. Enter the following command. Replace `` with any name that you want to use for the snapshot (e.g. `upgrade.db`). + + ```shell + rke etcd snapshot-save --config rancher-cluster.yml --name snapshot-name \ + --s3 --access-key S3_ACCESS_KEY --secret-key S3_SECRET_KEY \ + --bucket-name s3-bucket-name --s3-endpoint s3.amazonaws.com + ``` + +**Result:** RKE takes a snapshot of `etcd` running on each `etcd` node. The file is saved to `/opt/rke/etcd-snapshots`. It is also uploaded to the S3 compatible backend. + +### 2. Backup Local Snapshots to a Safe Location + +> **Note:** If you are using RKE v0.2.0, you can enable saving the backups to a S3 compatible backend directly and skip this step. After taking the `etcd` snapshots, save them to a safe location so that they're unaffected if your cluster experiences a disaster scenario. This location should be persistent. diff --git a/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md b/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md index 94093b8a135..f51bca614a3 100644 --- a/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md +++ b/content/rancher/v2.x/en/backups/restorations/ha-restoration/_index.md @@ -7,19 +7,19 @@ aliases: This procedure describes how to use RKE to restore a snapshot of the Rancher Kubernetes cluster. The cluster snapshot will include Kubernetes configuration and the Rancher database and state. +Additionally, the `pki.bundle.tar.gz` file usage is no longer required as v0.2.0 has changed how the [Kubernetes cluster state is stored]({{< baseurl >}}/rke/latest/en/installation/#kubernetes-cluster-state). + ## Restore Outline - - [1. Preparation](#1-preparation) -- [2. Place Snapshot and PKI Bundle](#2-place-snapshot-and-pki-bundle) +- [2. Place Snapshot](#2-place-snapshot) - [3. Configure RKE](#3-configure-rke) - [4. Restore Database](#4-restore-database) - [5. Bring Up the Cluster](#5-bring-up-the-cluster) -
### 1. Preparation @@ -29,11 +29,22 @@ Prepare by creating 3 new nodes to be the target for the restored Rancher instan We recommend that you start with fresh nodes and a clean state. Alternatively you can clear Kubernetes and Rancher configurations from the existing nodes. This will destroy the data on these nodes. See [Node Cleanup]({{< baseurl >}}/rancher/v2.x/en/faq/cleaning-cluster-nodes/) for the procedure. -> **IMPORTANT:** Before starting the restore make sure all the kubernetes services on the old cluster nodes are stopped. We recommend powering off the nodes to be sure. +> **IMPORTANT:** Before starting the restore make sure all the Kubernetes services on the old cluster nodes are stopped. We recommend powering off the nodes to be sure. -### 2. Place Snapshot and PKI Bundle +### 2. Place Snapshot +The snapshot used to restore your etcd cluster is handled differently based on your version of RKE. -Pick a one of the clean nodes. That node will be the "target node" for the initial restore. Place the snapshot and PKI certificate bundle files in the `/opt/rke/etcd-snapshots` directory on the "target node". +#### RKE v0.2.0+ + +As of RKE v0.2.0, snapshots could be saved in an S3 compatible backend. To restore your cluster from the snapshot stored in S3 compatible backend, you can skip this step and retrieve the snapshot in [Step 4: Restore Database](#4-restore-database). Otherwise, you will need to place the snapshot directly on the nodes. + +Pick one of the clean nodes. That node will be the "target node" for the initial restore. Place your snapshot in `/opt/rke/etcd-snapshots` on the target node. + +#### RKE v0.1.x + +When you take a snapshot, RKE saves a backup of the certificates, i.e. a file named `pki.bundle.tar.gz`, in the same location. The snapshot and PKI bundle file are required for the restore process, and they are expected to be in the same location. + +Pick one of the clean nodes. That node will be the "target node" for the initial restore. Place the snapshot and PKI certificate bundle files in the `/opt/rke/etcd-snapshots` directory on the target node. * Snapshot - `.db` * PKI Bundle - `pki.bundle.tar.gz` @@ -81,15 +92,54 @@ nodes: Use RKE with the new `rancher-cluster-restore.yml` configuration and restore the database to the single "target node". +RKE will create an `etcd` container with the restored database on the target node. This container will not complete the `etcd` initialization and stay in a running state until the cluster brought up in the next step. + +#### Restoring from a Local Snapshot + +When restoring etcd from a local snapshot, the snapshot is assumed to be located on the target node in the directory `/opt/rke/etcd-snapshots`. + +> **Note:** For RKE v0.1.x, the `pki.bundle.tar.gz` file is also expected to be in the same location. + ``` rke etcd snapshot-restore --name .db --config ./rancher-cluster-restore.yml ``` -> **Note:** RKE will create an `etcd` container with the restored database on the "target node". This container will not complete the `etcd` initialization and stay in a running state until the cluster brought up in the next step. +#### Restoring from a Snapshot in S3 + +_Available as of RKE v0.2.0_ + +When restoring etcd from a snapshot located in an S3 compatible backend, the command needs the S3 information in order to connect to the S3 backend and retrieve the snapshot. + +> **Note:** Ensure your `cluster.rkestate` is present before starting the restore, as this contains your certificate data for the cluster. + +``` +$ rke etcd snapshot-restore --config cluster.yml --name snapshot-name \ +--s3 --access-key S3_ACCESS_KEY --secret-key S3_SECRET_KEY \ +--bucket-name s3-bucket-name --s3-endpoint s3.amazonaws.com +``` + +#### Options for `rke etcd snapshot-restore` + +S3 specific options are only available for RKE v0.2.0+. + +| Option | Description | S3 Specific | +| --- | --- | ---| +| `--name` value | Specify snapshot name | | +| `--config` value | Specify an alternate cluster YAML file (default: "cluster.yml") [$RKE_CONFIG] | | +| `--s3` | Enabled backup to s3 |* | +| `--s3-endpoint` value | Specify s3 endpoint url (default: "s3.amazonaws.com") | * | +| `--access-key` value | Specify s3 accessKey | *| +| `--secret-key` value | Specify s3 secretKey | *| +| `--bucket-name` value | Specify s3 bucket name | *| +| `--region` value | Specify the s3 bucket location (optional) | *| +| `--ssh-agent-auth` | [Use SSH Agent Auth defined by SSH_AUTH_SOCK]({{< baseurl >}}/rke/latest/en/config-options/#ssh-agent) | | +| `--ignore-docker-version` | [Disable Docker version check]({{< baseurl >}}/rke/latest/en/config-options/#supported-docker-versions) | ### 5. Bring Up the Cluster -Use RKE and bring up the cluster on the single "target node". +Use RKE and bring up the cluster on the single "target node." + +> **Note:** For users running RKE v0.2.0+, ensure your `cluster.rkestate` is present before starting the restore, as this contains your certificate data for the cluster. ``` rke up --config ./rancher-cluster-restore.yml @@ -179,6 +229,6 @@ rke up --config ./rancher-cluster-restore.yml #### Finishing Up -Rancher should now be running and available to manage your Kubernetes clusters. Swap your Rancher DNS or Load Balancer endpoints to target the new cluster. Once this is done the agents on your managed clusters should automatically reconnect. This may take 10-15 minutes due to reconnect back off timeouts. +Rancher should now be running and available to manage your Kubernetes clusters. Swap your Rancher DNS or Load Balancer endpoints to target the new cluster. Once this is done the agents on your managed clusters should automatically reconnect. This may take 10-15 minutes due to reconnect back off timeouts. > **IMPORTANT:** Remember to save your new RKE config (`rancher-cluster-restore.yml`) and `kubectl` credentials (`kube_config_rancher-cluster-restore.yml`) files in a safe place for future maintenance. diff --git a/content/rancher/v2.x/en/cluster-admin/backing-up-etcd/_index.md b/content/rancher/v2.x/en/cluster-admin/backing-up-etcd/_index.md index eeb685b96cf..857ddd1f624 100644 --- a/content/rancher/v2.x/en/cluster-admin/backing-up-etcd/_index.md +++ b/content/rancher/v2.x/en/cluster-admin/backing-up-etcd/_index.md @@ -35,7 +35,7 @@ Rancher supports two different backup targets: #### Local Backup Target -By default, the `local` backup target is selected. The benefits of this option is that there is no external configuration. Snapshots are automatically saved locally to the etcd nodes in the [Rancher launched Kubernetes clusters]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/rke-clusters/). All recurring snapshots are taken at configured intervals. The downside of using the `local` backup target is that if there is a total disaster and _all_ etcd nodes are lost, there is no ability to restore the cluster. +By default, the `local` backup target is selected. The benefits of this option is that there is no external configuration. Snapshots are automatically saved locally to the etcd nodes in the [Rancher launched Kubernetes clusters]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/rke-clusters/) in `/opt/rke/etcd-snapshots`. All recurring snapshots are taken at configured intervals. The downside of using the `local` backup target is that if there is a total disaster and _all_ etcd nodes are lost, there is no ability to restore the cluster. #### S3 Backup Target diff --git a/content/rancher/v2.x/en/cluster-admin/nodes/_index.md b/content/rancher/v2.x/en/cluster-admin/nodes/_index.md index 5267a662c56..56019ecbecb 100644 --- a/content/rancher/v2.x/en/cluster-admin/nodes/_index.md +++ b/content/rancher/v2.x/en/cluster-admin/nodes/_index.md @@ -10,8 +10,6 @@ After you launch a Kubernetes cluster in Rancher, you can manage individual node To manage individual nodes, browse to the cluster that you want to manage and then select **Nodes** from the main menu. You can open the options menu for a node by clicking its **Ellipsis** icon (**...**). -![Node Options]({{< baseurl >}}/img/rancher/node-edit.png) - >**Note:** If you want to manage the _cluster_ and not individual nodes, see [Editing Clusters]({{< baseurl >}}/rancher/v2.x/en/k8s-in-rancher/editing-clusters). The following table lists which node options are available for each [type of cluster]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/#cluster-creation-options) in Rancher. Click the links in the **Option** column for more detailed information about each feature. @@ -45,11 +43,26 @@ _Draining_ is the process of first cordoning the node, and then evicting all its You can drain nodes that are in either a `cordoned` or `active` state. When you drain a node, the node is cordoned, the nodes are evaluated for conditions they must meet to be drained, and then (if it meets the conditions) the node evicts its pods. -However, you can override the conditions draining when you initiate the drain (see [below](#below)). You're also given an opportunity to set a grace period and timeout value. +However, you can override the conditions draining when you initiate the drain. You're also given an opportunity to set a grace period and timeout value. -![Drain]({{< baseurl >}}/img/rancher/node-drain.png) +The node draining options are different based on your version of Rancher. + +### Aggressive and Safe Draining Options for Rancher v2.2.x+ + +There are two drain modes: aggressive and safe. + +- **Aggressive Mode** + + In this mode, pods won't get rescheduled to a new node, even if they do not have a controller. Kubernetes expects you to have your own logic that handles the deletion of these pods. + + Kubernetes also expects the implementation to decide what to do with pods using emptyDir. If a pod uses emptyDir to store local data, you might not be able to safely delete it, since the data in the emptyDir will be deleted once the pod is removed from the node. Choosing aggressive mode will delete these pods. + +- **Safe Mode** + + If a node has standalone pods or ephemeral data it will be cordoned but not drained. + +### Aggressive and Safe Draining Options for Rancher Prior to v2.2.x - The following list describes each drain option: - **Even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet** @@ -64,15 +77,18 @@ The following list describes each drain option: If a pod uses emptyDir to store local data, you might not be able to safely delete it, since the data in the emptyDir will be deleted once the pod is removed from the node. Similar to the first option, Kubernetes expects the implementation to decide what to do with these pods. Choosing this option will delete these pods. -- **Grace Period** - The timeout given to each pod for cleaning things up, so they will have chance to exit gracefully. For example, when pods might need to finish any outstanding requests, roll back transactions or save state to some external storage. If negative, the default value specified in the pod will be used. +### Grace Period -- **Timeout** +The timeout given to each pod for cleaning things up, so they will have chance to exit gracefully. For example, when pods might need to finish any outstanding requests, roll back transactions or save state to some external storage. If negative, the default value specified in the pod will be used. - The amount of time drain should continue to wait before giving up. +### Timeout - >**Kubernetes Known Issue:** Currently, the [timeout setting](https://github.com/kubernetes/kubernetes/pull/64378) is not enforced while draining a node. This issue will be corrected as of Kubernetes 1.12. +The amount of time drain should continue to wait before giving up. + +>**Kubernetes Known Issue:** Currently, the [timeout setting](https://github.com/kubernetes/kubernetes/pull/64378) is not enforced while draining a node. This issue will be corrected as of Kubernetes 1.12. + +### Drained and Cordoned State If there's any error related to user input, the node enters a `cordoned` state because the drain failed. You can either correct the input and attempt to drain the node again, or you can abort by uncordoning the node. @@ -104,9 +120,6 @@ Use **Delete** to remove defective nodes from the cloud provider. When you the d For nodes hosted by an infrastructure provider, you can scale the number of nodes in each node pool by using the scale controls. This option isn't available for other cluster types. -![Scaling Nodes]({{< baseurl >}}/img/rancher/iaas-scale-nodes.png) - - ## SSH into a Node Hosted by an Infrastructure Provider For [nodes hosted by an infrastructure provider]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/rke-clusters/node-pools/), you have the option of downloading its SSH key so that you can connect to it remotely from your desktop. diff --git a/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/gke/_index.md b/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/gke/_index.md index 92c2f16db04..4813de514f1 100644 --- a/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/gke/_index.md +++ b/content/rancher/v2.x/en/cluster-provisioning/hosted-kubernetes-clusters/gke/_index.md @@ -12,9 +12,10 @@ Create a service account using [Google Cloud Platform](https://console.cloud.goo The service account requires the following roles: -- `project/viewer` -- `kubernetes-engine/admin` -- `service-account/user` +- **Compute Viewer:** `roles/compute.viewer` +- **Project Viewer:** `roles/viewer` +- **Kubernetes Engine Admin:** `roles/container.admin` +- **Service Account User:** `roles/iam.serviceAccountUser` [Google Documentation: Creating and Enabling Service Accounts](https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances) diff --git a/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/node-pools/azure/_index.md b/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/node-pools/azure/_index.md index 43bb3b1979c..d1f29074b38 100644 --- a/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/node-pools/azure/_index.md +++ b/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/node-pools/azure/_index.md @@ -28,7 +28,7 @@ Use {{< product >}} to create a Kubernetes cluster in Azure. {{< step_create-cloud-credential >}} - - **Placement** sets the geographical region where where your cluster is hosted and other location metadata. + - **Placement** sets the geographical region where your cluster is hosted and other location metadata. - **Network** configures the networking used in your cluster. diff --git a/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/options/_index.md b/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/options/_index.md index 827cbf57002..bfeafda0668 100644 --- a/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/options/_index.md +++ b/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/options/_index.md @@ -64,7 +64,7 @@ If you are using a private registry with authentication for your Docker images, _Available as of v2.2.0_ -Authorized Cluster Endpoint can be used to directly access the Kubernetes API server, without requiring communication through Rancher. This is enabled by default, using the IP of the node with the `controlplane` role and the default Kubernetes self signed certificates. It is recommended to create an FQDN pointing to a load balancer which load balances across your nodes with the `controlplane` role. If you are using private CA signed certificates on the load balancer, you have to supply the CA certificate which will be included in the generated kubeconfig to validate the certificate chain. See the [Kubeconfig Files]({{< baseurl >}}/rancher/v2.x/en/k8s-in-rancher/kubeconfig/) for more information. +Authorized Cluster Endpoint can be used to directly access the Kubernetes API server, without requiring communication through Rancher. This is enabled by default, using the IP of the node with the `controlplane` role and the default Kubernetes self signed certificates. It is recommended to create an FQDN pointing to a load balancer which load balances across your nodes with the `controlplane` role. If you are using private CA signed certificates on the load balancer, you have to supply the CA certificate which will be included in the generated kubeconfig to validate the certificate chain. See the [Kubeconfig Files]({{< baseurl >}}/rancher/v2.x/en/k8s-in-rancher/kubeconfig/) and [API Keys]({{< baseurl >}}/v2.x/en/user-settings/api-keys/#creating-an-api-key) documentation for more information. ### Advanced Cluster Options diff --git a/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/_index.md b/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/_index.md index b25c17b046c..9dcedd9d439 100644 --- a/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/_index.md +++ b/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/_index.md @@ -5,8 +5,8 @@ weight: 2240 >**Notes:** > ->- Windows support is new and improved for Rancher v2.3! ->- Still using v2.1.x or v2.2.x? As of v2.1.10 and v2.2.3, the previous Windows feature has been removed. See the windows documentation for [previous versions]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/docs-for-2.1-and-2.2/). +>- Configuring Windows clusters is new and improved for Rancher v2.3.0! +>- Still using v2.1.x or v2.2.x? See the documentation for how to provision Windows clusters on [previous versions]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/docs-for-2.1-and-2.2/). As of v2.1.10 and v2.2.4, the ability to provision Windows clusters has been removed in the 2.1.x and 2.2.x lines. _Available as of v2.3.0-alpha1_ @@ -50,7 +50,7 @@ To set up a custom cluster with support for Windows nodes and containers, you wi - [4. Add Linux Worker Node](#4-add-linux-worker-node) - [5. Add Windows Workers](#5-add-windows-workers) - [6. Cloud-host VM Routes Configuration for Host Gateway Mode (Optional)](#6-cloud-hosted-vm-routes-configuration-for-host-gateway-mode) - +- [7. Configuration for Azure Files (Optional)](#7-configuration-for-azure-files) ## 1. Provision Hosts @@ -209,4 +209,43 @@ Google GCE | For GCE, add a static route for each node: [Adding a Static Route]( Azure VM | For Azure, create a routing table: [Custom Routes: User-defined](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-networks-udr-overview#user-defined). -` ` +## 7. Configuration for Azure Files + +If you are using Azure VMs for your nodes, you can use [Azure files](https://docs.microsoft.com/en-us/azure/aks/azure-files-dynamic-pv) as a [storage class]({{< baseurl >}}/rancher/v2.x/en/cluster-admin/volumes-and-storage/#adding-storage-classes) for the cluster. + +In order to have the Azure platform create the required storage resources, follow these steps: + +1. [Configure the Azure cloud provider.]({{< baseurl >}}rancher/v2.x/en/cluster-provisioning/rke-clusters/options/cloud-providers/#azure) + +1. Configure `kubectl` to connect to your cluster. + +1. Copy the `ClusterRole` and `ClusterRoleBinding` manifest for service account. + + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + name: system:azure-cloud-provider + rules: + - apiGroups: [''] + resources: ['secrets'] + verbs: ['get','create'] + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + name: system:azure-cloud-provider + roleRef: + kind: ClusterRole + apiGroup: rbac.authorization.k8s.io + name: system:azure-cloud-provider + subjects: + - kind: ServiceAccount + name: persistent-volume-binder + namespace: kube-system + +1. Create these in your cluster using one of the follow command. + + ``` + # kubectl create -f + ``` diff --git a/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/docs-for-2.1-and-2.2/_index.md b/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/docs-for-2.1-and-2.2/_index.md index 5721f56958a..2aa36f0243d 100644 --- a/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/docs-for-2.1-and-2.2/_index.md +++ b/content/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/docs-for-2.1-and-2.2/_index.md @@ -3,9 +3,9 @@ title: v2.1.x and v2.2.x Windows Documentation (Experimental) weight: 9100 --- ->**Note:** This section describes the Windows feature as implemented in Rancher v2.1.x and v2.2.x. If you are using Rancher v2.3 or later, where Windows have been significantly improved, please refer to the new documentation for [v2.3 or later]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/). +>**Note:** This section describes how to provision Windows clusters in Rancher v2.1.x and v2.2.x. If you are using Rancher v2.3.0 or later, please refer to the new documentation for [v2.3.0 or later]({{< baseurl >}}/rancher/v2.x/en/cluster-provisioning/rke-clusters/windows-clusters/). -_Available from v2.1.0 to v2.1.9 and v2.2.0 to v2.2.2_ +_Available from v2.1.0 to v2.1.9 and v2.2.0 to v2.2.3_ >**Important:** > diff --git a/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md b/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md index 7c1c84b1972..87b9bc03c8f 100644 --- a/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md +++ b/content/rancher/v2.x/en/installation/air-gap-high-availability/install-rancher/_index.md @@ -107,8 +107,8 @@ By default, Rancher generates a CA and uses cert manger to issue the certificate --name rancher \ --namespace cattle-system \ --set hostname= \ - --set rancherImage=/rancher/rancher - --set ingress.tls.source=secret \ + --set rancherImage=/rancher/rancher \ + --set ingress.tls.source=secret ``` 1. See [Adding TLS Secrets]({{< baseurl >}}/rancher/v2.x/en/installation/ha/helm-rancher/tls-secrets/) to publish the certificate files so Rancher and the ingress controller can use them. diff --git a/content/rancher/v2.x/en/installation/ha/rke-add-on/layer-7-lb/_index.md b/content/rancher/v2.x/en/installation/ha/rke-add-on/layer-7-lb/_index.md index 93a1b4fb16b..8460a64160e 100644 --- a/content/rancher/v2.x/en/installation/ha/rke-add-on/layer-7-lb/_index.md +++ b/content/rancher/v2.x/en/installation/ha/rke-add-on/layer-7-lb/_index.md @@ -198,7 +198,7 @@ If you are using a Certificate Signed By A Recognized Certificate Authority, you ## 8. Configure FQDN -There is one reference to `` in the RKE config file. Replace this reference with the FQDN you chose in in [3. Configure DNS](#3-configure-dns). +There is one reference to `` in the RKE config file. Replace this reference with the FQDN you chose in [3. Configure DNS](#3-configure-dns). 1. Open `rancher-cluster.yml`. diff --git a/content/rancher/v2.x/en/installation/ha/rke-add-on/proxy/_index.md b/content/rancher/v2.x/en/installation/ha/rke-add-on/proxy/_index.md index b35ac7a9e09..9a0e7edb6e4 100644 --- a/content/rancher/v2.x/en/installation/ha/rke-add-on/proxy/_index.md +++ b/content/rancher/v2.x/en/installation/ha/rke-add-on/proxy/_index.md @@ -28,7 +28,7 @@ When using High Availability Installation, the environment variables need to be * [High Availability Installation with External Load Balancer (TCP/Layer 4) RKE Config File Template]({{< baseurl >}}/rancher/v2.x/en/installation/ha-server-install/#5-download-rke-config-file-template) * [High Availability Installation with External Load Balancer (HTTPS/Layer 7) RKE Config File Template]({{< baseurl >}}/rancher/v2.x/en/installation/ha-server-install-external-lb/#5-download-rke-config-file-template) -The environment variables should be defined in the `Deployment` inside the RKE Config File Template. You only have to add the the part starting with `env:` to (but not including) `ports:`. Make sure the indentation is identical to the preceding `name:`. Required values for `NO_PROXY` are: +The environment variables should be defined in the `Deployment` inside the RKE Config File Template. You only have to add the part starting with `env:` to (but not including) `ports:`. Make sure the indentation is identical to the preceding `name:`. Required values for `NO_PROXY` are: * `localhost` * `127.0.0.1` diff --git a/content/rancher/v2.x/en/installation/single-node/_index.md b/content/rancher/v2.x/en/installation/single-node/_index.md index dabf756c793..2b0a0f5e51a 100644 --- a/content/rancher/v2.x/en/installation/single-node/_index.md +++ b/content/rancher/v2.x/en/installation/single-node/_index.md @@ -97,7 +97,7 @@ For production environments, you also have the option of using [Let's Encrypt](h >- Open port `TCP/80` on your Linux host. The Let's Encrypt http-01 challenge can come from any source IP address, so port `TCP/80` must be open to all IP addresses. -After you fulfill the prerequisites, you can install Rancher using a Let's Encrypt certificate by running the following command. Replace `` with your your domain. +After you fulfill the prerequisites, you can install Rancher using a Let's Encrypt certificate by running the following command. Replace `` with your domain. docker run -d --restart=unless-stopped \ -p 80:80 -p 443:443 \ diff --git a/content/rancher/v2.x/en/installation/single-node/single-node-install-external-lb/_index.md b/content/rancher/v2.x/en/installation/single-node/single-node-install-external-lb/_index.md index 93623d655b1..a6d832a5a2c 100644 --- a/content/rancher/v2.x/en/installation/single-node/single-node-install-external-lb/_index.md +++ b/content/rancher/v2.x/en/installation/single-node/single-node-install-external-lb/_index.md @@ -4,7 +4,7 @@ weight: 252 aliases: - /rancher/v2.x/en/installation/single-node-install-external-lb/ --- -For development and testing environments that have a special requirement to terminate TLS/SSL at a load balancer instead of your Rancher Server container, deploy Rancher and configure a load balancer to work with it it conjunction. This install procedure walks you through deployment of Rancher using a single container, and then provides a sample configuration for a layer 7 Nginx load balancer. +For development and testing environments that have a special requirement to terminate TLS/SSL at a load balancer instead of your Rancher Server container, deploy Rancher and configure a load balancer to work with it conjunction. This install procedure walks you through deployment of Rancher using a single container, and then provides a sample configuration for a layer 7 Nginx load balancer. >**Want to skip the external load balancer?** > See [Single Node Installation]({{< baseurl >}}/rancher/v2.x/en/installation/single-node) instead. diff --git a/content/rancher/v2.x/en/k8s-in-rancher/horitzontal-pod-autoscaler/_index.md b/content/rancher/v2.x/en/k8s-in-rancher/horitzontal-pod-autoscaler/_index.md index 422bf82e033..c53c1c2706f 100644 --- a/content/rancher/v2.x/en/k8s-in-rancher/horitzontal-pod-autoscaler/_index.md +++ b/content/rancher/v2.x/en/k8s-in-rancher/horitzontal-pod-autoscaler/_index.md @@ -405,7 +405,7 @@ spec: 1. Test that pod autoscaling works as intended.

**To Test Autoscaling Using Resource Metrics:** {{% accordion id="observe-upscale-2-pods-cpu" label="Upscale to 2 Pods: CPU Usage Up to Target" %}} -Use your load testing tool to to scale up to two pods based on CPU Usage. +Use your load testing tool to scale up to two pods based on CPU Usage. 1. View your HPA. ``` @@ -491,7 +491,7 @@ Use your load testing tool to upspace to 3 pods based on CPU usage with `horizon ``` {{% /accordion %}} {{% accordion id="observe-downscale-1-pod" label="Downscale to 1 Pod: All Metrics Below Target" %}} -Use your load testing to to scale down to 1 pod when all metrics are below target for `horizontal-pod-autoscaler-downscale-delay` (5 minutes by default). +Use your load testing to scale down to 1 pod when all metrics are below target for `horizontal-pod-autoscaler-downscale-delay` (5 minutes by default). 1. Enter the following command. ``` @@ -794,7 +794,7 @@ To create HPA resources based on resource metrics such as CPU and memory use, yo ``` # kubectl -n kube-system logs metrics-server-6fbfb84cdd-t2fk9 ``` - Then review the log to confirm that that the `metrics-server` package is running. + Then review the log to confirm that the `metrics-server` package is running. {{% accordion id="metrics-server-run-check" label="Metrics Server Log Output" %}} I0723 08:09:56.193136 1 heapster.go:71] /metrics-server --source=kubernetes.summary_api:'' I0723 08:09:56.193574 1 heapster.go:72] Metrics Server version v0.2.1 @@ -816,7 +816,7 @@ To create HPA resources based on resource metrics such as CPU and memory use, yo ``` # kubectl get --raw /k8s/clusters//apis/metrics.k8s.io/v1beta1 ``` - If the the API is working correctly, you should receive output similar to the output below. + If the API is working correctly, you should receive output similar to the output below. ``` {"kind":"APIResourceList","apiVersion":"v1","groupVersion":"metrics.k8s.io/v1beta1","resources":[{"name":"nodes","singularName":"","namespaced":false,"kind":"NodeMetrics","verbs":["get","list"]},{"name":"pods","singularName":"","namespaced":true,"kind":"PodMetrics","verbs":["get","list"]}]} ``` @@ -825,7 +825,7 @@ To create HPA resources based on resource metrics such as CPU and memory use, yo ``` # kubectl get --raw /apis/metrics.k8s.io/v1beta1 ``` - If the the API is working correctly, you should receive output similar to the output below. + If the API is working correctly, you should receive output similar to the output below. ``` {"kind":"APIResourceList","apiVersion":"v1","groupVersion":"metrics.k8s.io/v1beta1","resources":[{"name":"nodes","singularName":"","namespaced":false,"kind":"NodeMetrics","verbs":["get","list"]},{"name":"pods","singularName":"","namespaced":true,"kind":"PodMetrics","verbs":["get","list"]}]} ``` diff --git a/content/rancher/v2.x/en/project-admin/namespaces/_index.md b/content/rancher/v2.x/en/project-admin/namespaces/_index.md index e56bfd6bc1c..96c03538fae 100644 --- a/content/rancher/v2.x/en/project-admin/namespaces/_index.md +++ b/content/rancher/v2.x/en/project-admin/namespaces/_index.md @@ -28,7 +28,7 @@ Create a new namespace to isolate apps and resources in a project. 1. From the **Global** view, open the project where you want to create a namespace. - >**Tip:** As a best practice, we recommend creating namespaces from the project level. However, cluster owners and members can can create them from the cluster level as well. + >**Tip:** As a best practice, we recommend creating namespaces from the project level. However, cluster owners and members can create them from the cluster level as well. 1. From the main menu, select **Namespace**. The click **Add Namespace**. diff --git a/content/rancher/v2.x/en/quick-start-guide/deployment/digital-ocean-qs/_index.md b/content/rancher/v2.x/en/quick-start-guide/deployment/digital-ocean-qs/_index.md index bfc0964705a..800757e7674 100644 --- a/content/rancher/v2.x/en/quick-start-guide/deployment/digital-ocean-qs/_index.md +++ b/content/rancher/v2.x/en/quick-start-guide/deployment/digital-ocean-qs/_index.md @@ -31,7 +31,7 @@ The following steps will quickly deploy a Rancher Server with a single node clus 6. Run `terraform init`. -7. To initiate the creation of the environment, run `terraform apply`. Then wait for the the following output: +7. To initiate the creation of the environment, run `terraform apply`. Then wait for the following output: ``` Apply complete! Resources: 2 added, 0 changed, 0 destroyed. diff --git a/content/rancher/v2.x/en/system-tools/_index.md b/content/rancher/v2.x/en/system-tools/_index.md index 2856637d961..db524751cd4 100644 --- a/content/rancher/v2.x/en/system-tools/_index.md +++ b/content/rancher/v2.x/en/system-tools/_index.md @@ -115,4 +115,4 @@ When you run the command below, all the resources listed [above](#remove) will b | ---------------------------------------------- | ------------ | `--kubeconfig , -c ` | The cluster's kubeconfig file | `--namespace , -n cattle-system` | Rancher 2.x deployment namespace (``). If no namespace is defined, the options defaults to `cattle-system`. -| `--force` | Skips the the interactive removal confirmation and removes the Rancher deployment without prompt. +| `--force` | Skips the interactive removal confirmation and removes the Rancher deployment without prompt. diff --git a/content/rancher/v2.x/en/troubleshooting/_index.md b/content/rancher/v2.x/en/troubleshooting/_index.md index b59f147334f..5177b1eff07 100644 --- a/content/rancher/v2.x/en/troubleshooting/_index.md +++ b/content/rancher/v2.x/en/troubleshooting/_index.md @@ -30,7 +30,7 @@ This section contains information to help you troubleshoot issues when using Ran - [Rancher HA]({{< baseurl >}}/rancher/v2.x/en/troubleshooting/rancherha/) - If you experience issues issues with your [High Availability (HA) Install]({{< baseurl >}}/rancher/v2.x/en/installation/ha/) + If you experience issues with your [High Availability (HA) Install]({{< baseurl >}}/rancher/v2.x/en/installation/ha/) - [Imported clusters]({{< baseurl >}}/rancher/v2.x/en/troubleshooting/imported-clusters/) diff --git a/content/rancher/v2.x/en/upgrades/upgrades/single-node-upgrade/_index.md b/content/rancher/v2.x/en/upgrades/upgrades/single-node-upgrade/_index.md index 1b04257eb02..e3be3ce786c 100644 --- a/content/rancher/v2.x/en/upgrades/upgrades/single-node-upgrade/_index.md +++ b/content/rancher/v2.x/en/upgrades/upgrades/single-node-upgrade/_index.md @@ -15,7 +15,7 @@ During upgrade, you'll enter a series of commands, filling placeholders with dat docker run --volumes-from rancher-data -v $PWD:/backup alpine tar zcvf /backup/rancher-data-backup--.tar.gz /var/lib/rancher ``` -In this command, `-` is the the version number and date of creation for a backup of Rancher. +In this command, `-` is the version number and date of creation for a backup of Rancher. Cross reference the image and reference table below to learn how to obtain this placeholder data. Write down or copy this information before starting the [procedure below](#completing-the-upgrade). diff --git a/content/rancher/v2.x/en/user-settings/api-keys/_index.md b/content/rancher/v2.x/en/user-settings/api-keys/_index.md index 6dbee301376..c83e9b70a44 100644 --- a/content/rancher/v2.x/en/user-settings/api-keys/_index.md +++ b/content/rancher/v2.x/en/user-settings/api-keys/_index.md @@ -25,9 +25,11 @@ API Keys are composed of four components: 2. Click **Add Key**. -3. **Optional:** Enter a description for the API key and select an expiration period. We recommend setting an expiration date. +3. **Optional:** Enter a description for the API key and select an expiration period or a scope. We recommend setting an expiration date. The API key won't be valid after expiration. Shorter expiration periods are more secure. + + A scope will limit the API key so that it will only work against the Kubernetes API of the specified cluster. If the cluster is configured with an Authroized Cluster Endpoint, you will be able to use a scoped token directly against the cluster's API without proxying through the Rancher server. See [Authorized Cluster Endpoints]({{< baseurl >}}/v2.x/en/cluster-provisioning/rke-clusters/options/#authorized-cluster-endpoint) for more information. 4. Click **Create**. diff --git a/content/rancher/v2.x/en/v1.6-migration/schedule-workloads/_index.md b/content/rancher/v2.x/en/v1.6-migration/schedule-workloads/_index.md index 826dd06bfee..67747de53c0 100644 --- a/content/rancher/v2.x/en/v1.6-migration/schedule-workloads/_index.md +++ b/content/rancher/v2.x/en/v1.6-migration/schedule-workloads/_index.md @@ -183,7 +183,7 @@ Rancher v1.6 included the ability to deploy [global services]({{< baseurl >}}/ra In Rancher v2.x, you can schedule a pod to each node using a [Kubernetes DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/), which is a specific type of workload ). A _DaemonSet_ functions exactly like a Rancher v1.6 global service. The Kubernetes scheduler deploys a pod on each node of the cluster, and as new nodes are added, the scheduler will start new pods on them provided they match the scheduling requirements of the workload. Additionally, in v2.x, you can also limit a DaemonSet to be deployed to nodes that have a specific label. -To create a daemonset while configuring a workload, choose **Run one pod on each node** from the the **Workload Type** options. +To create a daemonset while configuring a workload, choose **Run one pod on each node** from the **Workload Type** options. ### Scheduling Pods Using Resource Constraints diff --git a/content/rke/latest/en/cert-mgmt/_index.md b/content/rke/latest/en/cert-mgmt/_index.md index 765826121bc..5d202d6bbdc 100644 --- a/content/rke/latest/en/cert-mgmt/_index.md +++ b/content/rke/latest/en/cert-mgmt/_index.md @@ -80,7 +80,7 @@ INFO[0033] [worker] Successfully restarted Worker Plane.. ### Rotating the CA and all service certificates -If the CA certificate needs to be rotated, you are required to rotate all the services certificates as they need to be signed with the newly rotated CA certificate. To include rotating the CA with the service certificates, add the `--rotate-ca` option. After the the CA and all the service certificates are rotated, these services will automatically be restarted to start using the new certificate. +If the CA certificate needs to be rotated, you are required to rotate all the services certificates as they need to be signed with the newly rotated CA certificate. To include rotating the CA with the service certificates, add the `--rotate-ca` option. After the CA and all the service certificates are rotated, these services will automatically be restarted to start using the new certificate. Rotating the CA certificate will result in restarting other system pods, that will also use the new CA certificate. This includes: diff --git a/content/rke/latest/en/config-options/add-ons/_index.md b/content/rke/latest/en/config-options/add-ons/_index.md index b15e5346947..8a659431c83 100644 --- a/content/rke/latest/en/config-options/add-ons/_index.md +++ b/content/rke/latest/en/config-options/add-ons/_index.md @@ -18,7 +18,7 @@ RKE only adds additional add-ons when using `rke up` multiple times. RKE does ** As of v0.1.8, RKE will update an add-on if it is the same name. -Prior to v0.1.8, update any add-ons by by using `kubectl edit`. +Prior to v0.1.8, update any add-ons by using `kubectl edit`. ## Critical and Non-Critical Add-ons diff --git a/content/rke/latest/en/config-options/add-ons/user-defined-add-ons/_index.md b/content/rke/latest/en/config-options/add-ons/user-defined-add-ons/_index.md index 6a03f9f418d..3f2dd072f91 100644 --- a/content/rke/latest/en/config-options/add-ons/user-defined-add-ons/_index.md +++ b/content/rke/latest/en/config-options/add-ons/user-defined-add-ons/_index.md @@ -18,7 +18,7 @@ RKE only adds additional add-ons when using `rke up` multiple times. RKE does ** As of v0.1.8, RKE will update an add-on if it is the same name. -Prior to v0.1.8, update any add-ons by by using `kubectl edit`. +Prior to v0.1.8, update any add-ons by using `kubectl edit`. ## In-line Add-ons diff --git a/content/rke/latest/en/etcd-snapshots/_index.md b/content/rke/latest/en/etcd-snapshots/_index.md index f17de91087c..b691f0e8f11 100644 --- a/content/rke/latest/en/etcd-snapshots/_index.md +++ b/content/rke/latest/en/etcd-snapshots/_index.md @@ -158,14 +158,18 @@ $ rke etcd snapshot-restore --config cluster.yml --name mysnapshot _Available as of v0.2.0_ +> **Note:** Ensure your `cluster.rkestate` is present before starting the restore, as this contains your certificate data for the cluster + When restoring etcd from a snapshot located in S3, the command needs the S3 information in order to connect to the S3 backend and retrieve the snapshot. -``` +```shell $ rke etcd snapshot-restore --config cluster.yml --name snapshot-name \ --s3 --access-key S3_ACCESS_KEY --secret-key S3_SECRET_KEY \ --bucket-name s3-bucket-name --s3-endpoint s3.amazonaws.com ``` -## Example +> **Note:** if you were restoring a cluster that had rancher installed the UI should start-up after a few minutes; you don't need to re-run helm. + +### Example Scenario of restoring from a Local Snapshot In this example, the Kubernetes cluster was deployed on two AWS nodes. @@ -185,7 +189,7 @@ $ rke etcd snapshot-save --name snapshot.db --config cluster.yml ![etcd snapshot]({{< baseurl >}}/img/rke/rke-etcd-backup.png) -### Store the Snapshot Externally to S3 +### Store the Snapshot Externally in S3 As of v0.2.0, this step is no longer required, as RKE can upload and download snapshots automatically from S3 by adding in [S3 options](#options-for-rke-etcd-snapshot-save) when running the `rke etcd snapshot-save` command. @@ -253,7 +257,7 @@ nodes: After the new node is added to the `cluster.yml`, run `rke etcd snapshot-restore` to launch `etcd` from the backup. The snapshot and `pki.bundle.tar.gz` file are expected to be saved at `/opt/rke/etcd-snapshots`. As of v0.2.0, if you want to directly retrieve the snapshot from S3, add in the [S3 options](#options-for-rke-etcd-snapshot-restore). -> **Note:** As of v0.2.0, the file **pki.bundle.tar.gz** is no longer required for the restore process. +> **Note:** As of v0.2.0, the file **pki.bundle.tar.gz** is no longer required for the restore process as the certificates required to restore are preserved within the `cluster.rkestate` ``` $ rke etcd snapshot-restore --name snapshot.db --config cluster.yml @@ -294,3 +298,6 @@ docker container inspect rke-bundle-cert ``` The important thing to note is the mounts of the container and location of the **pki.bundle.tar.gz**. + + + diff --git a/content/rke/latest/en/os/_index.md b/content/rke/latest/en/os/_index.md index 56df0dea9c6..44c16a28a2c 100644 --- a/content/rke/latest/en/os/_index.md +++ b/content/rke/latest/en/os/_index.md @@ -99,7 +99,7 @@ rpm -q docker-ce When using the upstream Docker packages, please follow [Manage Docker as a non-root user](https://docs.docker.com/install/linux/linux-postinstall/#manage-docker-as-a-non-root-user). #### Using RHEL/CentOS packaged Docker -If you are using the Docker Docker package supplied by Red Hat / CentOS, the package name is `docker`. You can check the installed package by executing: +If you are using the Docker package supplied by Red Hat / CentOS, the package name is `docker`. You can check the installed package by executing: ``` rpm -q docker diff --git a/layouts/_default/list.html b/layouts/_default/list.html index fe85f2c755f..5ce699f3f0d 100644 --- a/layouts/_default/list.html +++ b/layouts/_default/list.html @@ -6,96 +6,288 @@ {{ end }} {{ define "main" }} -
+
+
+
+
+
+
+
-
+
- + +
+
+
+ {{ with .Params.Title }} +

{{ . }}

+
+ {{end}} + + {{ if .Params.ctaBanner }} + {{ with index .Site.Data.cta .Params.ctaBanner }} +
+

{{ .header }}

-
- - {{ with .Params.Title }} -

{{ . }}

-
- {{end}} - - {{ if .Params.ctaBanner }} - {{ with index .Site.Data.cta .Params.ctaBanner }} -
-

{{ .header }}

- {{ .button }} -
- {{ end }} - {{ end }} - -
- - - - {{ .Content }} - - {{ $paginator := .Scratch.Get "paginator" }} - {{ range $paginator.Pages }} -
-
-

{{.Title}}

- - {{ if .Params.Image }} -
{{ .Params.Title }}
- {{end}} - -

{{ .Summary | safeHTML }}

- {{ if .Truncated }} - + {{ end }} + {{ end }} + +
+ + + + {{ .Content }} + + {{ $paginator := .Scratch.Get "paginator" }} + {{ range $paginator.Pages }} +
+
+

{{.Title}}

+ + {{ if .Params.Image }} +
{{ .Params.Title }}
+ {{end}} + +

{{ .Summary | safeHTML }}

+ {{ if .Truncated }} + + {{ end }} +
+
+
+ + {{ with .Params.Author }} +
person_outline By: {{ . }}
+ {{end}} + + {{ if eq .Section "events" }} + {{ with .Params.EventDate }} +
event {{ . }}
+ {{end}} + + {{ else }} + + {{ with .Params.Date }} +
event {{ .Format "January 2, 2006" }}
+ {{end}} + {{end}} + + {{ if eq .Section "blog" }} +
timer Read Time: {{.ReadingTime}} minutes
+ {{end}} + + {{ with .Params.Location }} +
location_on {{ . }}
+ {{end}} + +
+
{{ end }}
-
-
- - {{ with .Params.Author }} -
person_outline By: {{ . }}
- {{end}} - - {{ if eq .Section "events" }} - {{ with .Params.EventDate }} -
event {{ . }}
- {{end}} - - {{ else }} - - {{ with .Params.Date }} -
event {{ .Format "January 2, 2006" }}
- {{end}} - {{end}} - - {{ if eq .Section "blog" }} -
timer Read Time: {{.ReadingTime}} minutes
- {{end}} - - {{ with .Params.Location }} -
location_on {{ . }}
- {{end}} - -
-
-
- {{ end }} + {{ template "_internal/pagination.html" . }} + +
{{ partial "page-edit.html" . }}
+
+
- {{ template "_internal/pagination.html" . }} - -
{{ partial "page-edit.html" . }}
- - +
-
+
+ + + {{ end }} diff --git a/layouts/index.html b/layouts/index.html index ef8bfb08221..466c351c042 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -1,19 +1,4 @@ -{{ define "hero" }} -
-
-
-
- {{ with .Params.pageHeader }} -

{{ . }}

- {{end}} - {{ with .Params.description }} -

{{ . }}

- {{end}} -
-
-
-
-{{ end }} + {{ define "main" }}
diff --git a/layouts/partials/docs-side-nav.html b/layouts/partials/docs-side-nav.html index f506673c6d2..964e25524a5 100644 --- a/layouts/partials/docs-side-nav.html +++ b/layouts/partials/docs-side-nav.html @@ -12,53 +12,78 @@ {{end}} -