diff --git a/website/site-dist/.nojekyll b/website/site-dist/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/website/site-dist/001e0081.4a700ba3.js b/website/site-dist/001e0081.4a700ba3.js new file mode 100644 index 0000000000..6c733fc1d2 --- /dev/null +++ b/website/site-dist/001e0081.4a700ba3.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{149:function(e,t,n){"use strict";n.d(t,"a",(function(){return p})),n.d(t,"b",(function(){return m}));var r=n(0),a=n.n(r);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=a.a.createContext({}),b=function(e){var t=a.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p=function(e){var t=b(e.components);return a.a.createElement(l.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},u=a.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,o=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),p=b(n),u=r,m=p["".concat(o,".").concat(u)]||p[u]||d[u]||i;return n?a.a.createElement(m,c(c({ref:t},l),{},{components:n})):a.a.createElement(m,c({ref:t},l))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,o=new Array(i);o[0]=u;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:r,o[1]=c;for(var l=2;l=0||(a[i]=e[i]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,i)&&(a[i]=e[i])}return a}var o=a.a.createContext({}),b=function(e){var t=a.a.useContext(o),i=t;return e&&(i="function"==typeof e?e(t):c(c({},t),e)),i},p=function(e){var t=b(e.components);return a.a.createElement(o.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},d=a.a.forwardRef((function(e,t){var i=e.components,n=e.mdxType,r=e.originalType,l=e.parentName,o=s(e,["components","mdxType","originalType","parentName"]),p=b(i),d=n,h=p["".concat(l,".").concat(d)]||p[d]||u[d]||r;return i?a.a.createElement(h,c(c({ref:t},o),{},{components:i})):a.a.createElement(h,c({ref:t},o))}));function h(e,t){var i=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var r=i.length,l=new Array(r);l[0]=d;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:n,l[1]=c;for(var o=2;o=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var b=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var i=n.a.createContext({}),p=function(e){var t=n.a.useContext(i),a=t;return e&&(a="function"==typeof e?e(t):l(l({},t),e)),a},u=function(e){var t=p(e.components);return n.a.createElement(i.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.a.createElement(n.a.Fragment,{},t)}},O=n.a.forwardRef((function(e,t){var a=e.components,r=e.mdxType,b=e.originalType,c=e.parentName,i=o(e,["components","mdxType","originalType","parentName"]),u=p(a),O=r,d=u["".concat(c,".").concat(O)]||u[O]||s[O]||b;return a?n.a.createElement(d,l(l({ref:t},i),{},{components:a})):n.a.createElement(d,l({ref:t},i))}));function d(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var b=a.length,c=new Array(b);c[0]=O;var l={};for(var o in t)hasOwnProperty.call(t,o)&&(l[o]=t[o]);l.originalType=e,l.mdxType="string"==typeof e?e:r,c[1]=l;for(var i=2;i Angular)"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),Object(b.b)("a",Object(r.a)({parentName:"td"},{href:"https://github.com/cloudfoundry/stratos/issues/1972"}),"#","1972")),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),Object(b.b)("a",Object(r.a)({parentName:"td"},{href:"/docs/planning/angular"}),"Notes"))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"2"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"1st class support for service plan & service instance"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),Object(b.b)("a",Object(r.a)({parentName:"td"},{href:"https://github.com/cloudfoundry/stratos/issues/1391"}),"#","1391")),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),Object(b.b)("a",Object(r.a)({parentName:"td"},{href:"/docs/planning/services"}),"Notes"))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"3"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"Add support for Application and CF Metrics"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),Object(b.b)("a",Object(r.a)({parentName:"td"},{href:"https://github.com/cloudfoundry/stratos/issues/1985"}),"#","1985")),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),Object(b.b)("a",Object(r.a)({parentName:"td"},{href:"/docs/planning/metrics"}),"Notes"))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"4"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"Support UAA login UX directly (SSO)"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),Object(b.b)("a",Object(r.a)({parentName:"td"},{href:"https://github.com/cloudfoundry/stratos/issues/1384"}),"#","1384")),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"5"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"Support per-endpoint Client ID and Client Secret"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),Object(b.b)("a",Object(r.a)({parentName:"td"},{href:"https://github.com/cloudfoundry/stratos/issues/2220"}),"#","2220")),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"6"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"Bring Orgs and Spaces view to top-level"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),Object(b.b)("a",Object(r.a)({parentName:"td"},{href:"https://github.com/cloudfoundry/stratos/issues/2619"}),"#","2619")),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"7"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),"Deploy application: Enable deploying from private Git repositories"),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}),Object(b.b)("a",Object(r.a)({parentName:"td"},{href:"https://github.com/cloudfoundry/stratos/issues/1442"}),"#","1442")),Object(b.b)("td",Object(r.a)({parentName:"tr"},{align:null}))))))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/website/site-dist/1.ac640629.js b/website/site-dist/1.ac640629.js new file mode 100644 index 0000000000..c127965af8 --- /dev/null +++ b/website/site-dist/1.ac640629.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{150:function(e,t,r){"use strict";var n=r(0),o=r(48);t.a=function(){return Object(n.useContext)(o.a)}},151:function(e,t,r){"use strict";function n(e){var t,r,o="";if("string"==typeof e||"number"==typeof e)o+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t(!h&&p&&window.docusaurus.prefetch(l),()=>{h&&b&&b.disconnect()}),[l,h,p]),l&&p&&!l.startsWith("#")?o.a.createElement(y,Object.assign({},r,{onMouseEnter:()=>{d.current||(window.docusaurus.preload(l),d.current=!0)},innerRef:e=>{var t,r;h&&e&&p&&(t=e,r=()=>{window.docusaurus.prefetch(l)},b=new window.IntersectionObserver(e=>{e.forEach(e=>{t===e.target&&(e.isIntersecting||e.intersectionRatio>0)&&(b.unobserve(t),b.disconnect(),r())})}),b.observe(t))},to:l})):o.a.createElement("a",Object.assign({href:l},!p&&{target:"_blank",rel:"noopener noreferrer"},r))}},153:function(e,t,r){"use strict";r.d(t,"a",(function(){return i}));var n=r(150),o=r(154);function i(e,{forcePrependBaseUrl:t=!1,absolute:r=!1}={}){const{siteConfig:{baseUrl:i="/",url:a}={}}=Object(n.a)();if(!e)return e;if(t)return i+e;if(!Object(o.a)(e))return e;const c=i+e.replace(/^\//,"");return r?a+c:c}},154:function(e,t,r){"use strict";function n(e){return!1===/^(https?:|\/\/|mailto:|tel:)/.test(e)}r.d(t,"a",(function(){return n}))},158:function(e,t,r){"use strict";var n=r(0),o=r.n(n),i=r(167);t.a=function(e){return o.a.createElement(i.a,Object.assign({},e))}},167:function(e,t,r){"use strict";(function(e){r.d(t,"a",(function(){return he}));var n,o,i,a,c=r(9),u=r.n(c),s=r(168),f=r.n(s),l=r(169),p=r.n(l),d=r(0),y=r.n(d),h=r(36),b=r.n(h),m="bodyAttributes",v="htmlAttributes",T="titleAttributes",g={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title"},w=(Object.keys(g).map((function(e){return g[e]})),"charset"),O="cssText",A="href",C="http-equiv",E="innerHTML",S="itemprop",j="name",P="property",k="rel",I="src",L="target",x={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},M="defaultTitle",N="defer",R="encodeSpecialCharacters",_="onChangeClientState",B="titleTemplate",D=Object.keys(x).reduce((function(e,t){return e[x[t]]=t,e}),{}),H=[g.NOSCRIPT,g.SCRIPT,g.STYLE],q="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},U=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},Y=function(){function e(e,t){for(var r=0;r=0||Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=e[n]);return r},K=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t},W=function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return!1===t?String(e):String(e).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")},V=function(e){var t=X(e,g.TITLE),r=X(e,B);if(r&&t)return r.replace(/%s/g,(function(){return Array.isArray(t)?t.join(""):t}));var n=X(e,M);return t||n||void 0},J=function(e){return X(e,_)||function(){}},$=function(e,t){return t.filter((function(t){return void 0!==t[e]})).map((function(t){return t[e]})).reduce((function(e,t){return F({},e,t)}),{})},G=function(e,t){return t.filter((function(e){return void 0!==e[g.BASE]})).map((function(e){return e[g.BASE]})).reverse().reduce((function(t,r){if(!t.length)for(var n=Object.keys(r),o=0;o=0;r--){var n=e[r];if(n.hasOwnProperty(t))return n[t]}return null},Z=(n=Date.now(),function(e){var t=Date.now();t-n>16?(n=t,e(t)):setTimeout((function(){Z(e)}),0)}),ee=function(e){return clearTimeout(e)},te="undefined"!=typeof window?window.requestAnimationFrame&&window.requestAnimationFrame.bind(window)||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||Z:e.requestAnimationFrame||Z,re="undefined"!=typeof window?window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||ee:e.cancelAnimationFrame||ee,ne=function(e){return console&&"function"==typeof console.warn&&console.warn(e)},oe=null,ie=function(e,t){var r=e.baseTag,n=e.bodyAttributes,o=e.htmlAttributes,i=e.linkTags,a=e.metaTags,c=e.noscriptTags,u=e.onChangeClientState,s=e.scriptTags,f=e.styleTags,l=e.title,p=e.titleAttributes;ue(g.BODY,n),ue(g.HTML,o),ce(l,p);var d={baseTag:se(g.BASE,r),linkTags:se(g.LINK,i),metaTags:se(g.META,a),noscriptTags:se(g.NOSCRIPT,c),scriptTags:se(g.SCRIPT,s),styleTags:se(g.STYLE,f)},y={},h={};Object.keys(d).forEach((function(e){var t=d[e],r=t.newTags,n=t.oldTags;r.length&&(y[e]=r),n.length&&(h[e]=d[e].oldTags)})),t&&t(),u(e,y,h)},ae=function(e){return Array.isArray(e)?e.join(""):e},ce=function(e,t){void 0!==e&&document.title!==e&&(document.title=ae(e)),ue(g.TITLE,t)},ue=function(e,t){var r=document.getElementsByTagName(e)[0];if(r){for(var n=r.getAttribute("data-react-helmet"),o=n?n.split(","):[],i=[].concat(o),a=Object.keys(t),c=0;c=0;l--)r.removeAttribute(i[l]);o.length===i.length?r.removeAttribute("data-react-helmet"):r.getAttribute("data-react-helmet")!==a.join(",")&&r.setAttribute("data-react-helmet",a.join(","))}},se=function(e,t){var r=document.head||document.querySelector(g.HEAD),n=r.querySelectorAll(e+"[data-react-helmet]"),o=Array.prototype.slice.call(n),i=[],a=void 0;return t&&t.length&&t.forEach((function(t){var r=document.createElement(e);for(var n in t)if(t.hasOwnProperty(n))if(n===E)r.innerHTML=t.innerHTML;else if(n===O)r.styleSheet?r.styleSheet.cssText=t.cssText:r.appendChild(document.createTextNode(t.cssText));else{var c=void 0===t[n]?"":t[n];r.setAttribute(n,c)}r.setAttribute("data-react-helmet","true"),o.some((function(e,t){return a=t,r.isEqualNode(e)}))?o.splice(a,1):i.push(r)})),o.forEach((function(e){return e.parentNode.removeChild(e)})),i.forEach((function(e){return r.appendChild(e)})),{oldTags:o,newTags:i}},fe=function(e){return Object.keys(e).reduce((function(t,r){var n=void 0!==e[r]?r+'="'+e[r]+'"':""+r;return t?t+" "+n:n}),"")},le=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return Object.keys(e).reduce((function(t,r){return t[x[r]||r]=e[r],t}),t)},pe=function(e,t,r){switch(e){case g.TITLE:return{toComponent:function(){return e=t.title,r=t.titleAttributes,(n={key:e})["data-react-helmet"]=!0,o=le(r,n),[y.a.createElement(g.TITLE,o,e)];var e,r,n,o},toString:function(){return function(e,t,r,n){var o=fe(r),i=ae(t);return o?"<"+e+' data-react-helmet="true" '+o+">"+W(i,n)+"":"<"+e+' data-react-helmet="true">'+W(i,n)+""}(e,t.title,t.titleAttributes,r)}};case m:case v:return{toComponent:function(){return le(t)},toString:function(){return fe(t)}};default:return{toComponent:function(){return function(e,t){return t.map((function(t,r){var n,o=((n={key:r})["data-react-helmet"]=!0,n);return Object.keys(t).forEach((function(e){var r=x[e]||e;if(r===E||r===O){var n=t.innerHTML||t.cssText;o.dangerouslySetInnerHTML={__html:n}}else o[r]=t[e]})),y.a.createElement(e,o)}))}(e,t)},toString:function(){return function(e,t,r){return t.reduce((function(t,n){var o=Object.keys(n).filter((function(e){return!(e===E||e===O)})).reduce((function(e,t){var o=void 0===n[t]?t:t+'="'+W(n[t],r)+'"';return e?e+" "+o:o}),""),i=n.innerHTML||n.cssText||"",a=-1===H.indexOf(e);return t+"<"+e+' data-react-helmet="true" '+o+(a?"/>":">"+i+"")}),"")}(e,t,r)}}}},de=function(e){var t=e.baseTag,r=e.bodyAttributes,n=e.encode,o=e.htmlAttributes,i=e.linkTags,a=e.metaTags,c=e.noscriptTags,u=e.scriptTags,s=e.styleTags,f=e.title,l=void 0===f?"":f,p=e.titleAttributes;return{base:pe(g.BASE,t,n),bodyAttributes:pe(m,r,n),htmlAttributes:pe(v,o,n),link:pe(g.LINK,i,n),meta:pe(g.META,a,n),noscript:pe(g.NOSCRIPT,c,n),script:pe(g.SCRIPT,u,n),style:pe(g.STYLE,s,n),title:pe(g.TITLE,{title:l,titleAttributes:p},n)}},ye=f()((function(e){return{baseTag:G([A,L],e),bodyAttributes:$(m,e),defer:X(e,N),encode:X(e,R),htmlAttributes:$(v,e),linkTags:Q(g.LINK,[k,A],e),metaTags:Q(g.META,[j,w,C,P,S],e),noscriptTags:Q(g.NOSCRIPT,[E],e),onChangeClientState:J(e),scriptTags:Q(g.SCRIPT,[I,E],e),styleTags:Q(g.STYLE,[O],e),title:V(e),titleAttributes:$(T,e)}}),(function(e){oe&&re(oe),e.defer?oe=te((function(){ie(e,(function(){oe=null}))})):(ie(e),oe=null)}),de)((function(){return null})),he=(o=ye,a=i=function(e){function t(){return U(this,t),K(this,e.apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t.prototype.shouldComponentUpdate=function(e){return!p()(this.props,e)},t.prototype.mapNestedChildrenToProps=function(e,t){if(!t)return null;switch(e.type){case g.SCRIPT:case g.NOSCRIPT:return{innerHTML:t};case g.STYLE:return{cssText:t}}throw new Error("<"+e.type+" /> elements are self-closing and can not contain children. Refer to our API for more information.")},t.prototype.flattenArrayTypeChildren=function(e){var t,r=e.child,n=e.arrayTypeChildren,o=e.newChildProps,i=e.nestedChildren;return F({},n,((t={})[r.type]=[].concat(n[r.type]||[],[F({},o,this.mapNestedChildrenToProps(r,i))]),t))},t.prototype.mapObjectTypeChildren=function(e){var t,r,n=e.child,o=e.newProps,i=e.newChildProps,a=e.nestedChildren;switch(n.type){case g.TITLE:return F({},o,((t={})[n.type]=a,t.titleAttributes=F({},i),t));case g.BODY:return F({},o,{bodyAttributes:F({},i)});case g.HTML:return F({},o,{htmlAttributes:F({},i)})}return F({},o,((r={})[n.type]=F({},i),r))},t.prototype.mapArrayTypeChildrenToProps=function(e,t){var r=F({},t);return Object.keys(e).forEach((function(t){var n;r=F({},r,((n={})[t]=e[t],n))})),r},t.prototype.warnOnInvalidChildren=function(e,t){return!0},t.prototype.mapChildrenToProps=function(e,t){var r=this,n={};return y.a.Children.forEach(e,(function(e){if(e&&e.props){var o=e.props,i=o.children,a=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return Object.keys(e).reduce((function(t,r){return t[D[r]||r]=e[r],t}),t)}(z(o,["children"]));switch(r.warnOnInvalidChildren(e,i),e.type){case g.LINK:case g.META:case g.NOSCRIPT:case g.SCRIPT:case g.STYLE:n=r.flattenArrayTypeChildren({child:e,arrayTypeChildren:n,newChildProps:a,nestedChildren:i});break;default:t=r.mapObjectTypeChildren({child:e,newProps:t,newChildProps:a,nestedChildren:i})}}})),t=this.mapArrayTypeChildrenToProps(n,t)},t.prototype.render=function(){var e=this.props,t=e.children,r=z(e,["children"]),n=F({},r);return t&&(n=this.mapChildrenToProps(t,n)),y.a.createElement(o,n)},Y(t,null,[{key:"canUseDOM",set:function(e){o.canUseDOM=e}}]),t}(y.a.Component),i.propTypes={base:u.a.object,bodyAttributes:u.a.object,children:u.a.oneOfType([u.a.arrayOf(u.a.node),u.a.node]),defaultTitle:u.a.string,defer:u.a.bool,encodeSpecialCharacters:u.a.bool,htmlAttributes:u.a.object,link:u.a.arrayOf(u.a.object),meta:u.a.arrayOf(u.a.object),noscript:u.a.arrayOf(u.a.object),onChangeClientState:u.a.func,script:u.a.arrayOf(u.a.object),style:u.a.arrayOf(u.a.object),title:u.a.string,titleAttributes:u.a.object,titleTemplate:u.a.string},i.defaultProps={defer:!0,encodeSpecialCharacters:!0},i.peek=o.peek,i.rewind=function(){var e=o.rewind();return e||(e=de({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}})),e},a);he.renderStatic=he.rewind}).call(this,r(52))},168:function(e,t,r){"use strict";var n,o=r(0),i=(n=o)&&"object"==typeof n&&"default"in n?n.default:n;function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var c=!("undefined"==typeof window||!window.document||!window.document.createElement);e.exports=function(e,t,r){if("function"!=typeof e)throw new Error("Expected reducePropsToState to be a function.");if("function"!=typeof t)throw new Error("Expected handleStateChangeOnClient to be a function.");if(void 0!==r&&"function"!=typeof r)throw new Error("Expected mapStateOnServer to either be undefined or a function.");return function(n){if("function"!=typeof n)throw new Error("Expected WrappedComponent to be a React component.");var u,s=[];function f(){u=e(s.map((function(e){return e.props}))),l.canUseDOM?t(u):r&&(u=r(u))}var l=function(e){var t,r;function o(){return e.apply(this,arguments)||this}r=e,(t=o).prototype=Object.create(r.prototype),t.prototype.constructor=t,t.__proto__=r,o.peek=function(){return u},o.rewind=function(){if(o.canUseDOM)throw new Error("You may only call rewind() on the server. Call peek() to read the current state.");var e=u;return u=void 0,s=[],e};var a=o.prototype;return a.UNSAFE_componentWillMount=function(){s.push(this),f()},a.componentDidUpdate=function(){f()},a.componentWillUnmount=function(){var e=s.indexOf(this);s.splice(e,1),f()},a.render=function(){return i.createElement(n,this.props)},o}(o.PureComponent);return a(l,"displayName","SideEffect("+function(e){return e.displayName||e.name||"Component"}(n)+")"),a(l,"canUseDOM",c),l}}},169:function(e,t){var r="undefined"!=typeof Element,n="function"==typeof Map,o="function"==typeof Set,i="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;e.exports=function(e,t){try{return function e(t,a){if(t===a)return!0;if(t&&a&&"object"==typeof t&&"object"==typeof a){if(t.constructor!==a.constructor)return!1;var c,u,s,f;if(Array.isArray(t)){if((c=t.length)!=a.length)return!1;for(u=c;0!=u--;)if(!e(t[u],a[u]))return!1;return!0}if(n&&t instanceof Map&&a instanceof Map){if(t.size!==a.size)return!1;for(f=t.entries();!(u=f.next()).done;)if(!a.has(u.value[0]))return!1;for(f=t.entries();!(u=f.next()).done;)if(!e(u.value[1],a.get(u.value[0])))return!1;return!0}if(o&&t instanceof Set&&a instanceof Set){if(t.size!==a.size)return!1;for(f=t.entries();!(u=f.next()).done;)if(!a.has(u.value[0]))return!1;return!0}if(i&&ArrayBuffer.isView(t)&&ArrayBuffer.isView(a)){if((c=t.length)!=a.length)return!1;for(u=c;0!=u--;)if(t[u]!==a[u])return!1;return!0}if(t.constructor===RegExp)return t.source===a.source&&t.flags===a.flags;if(t.valueOf!==Object.prototype.valueOf)return t.valueOf()===a.valueOf();if(t.toString!==Object.prototype.toString)return t.toString()===a.toString();if((c=(s=Object.keys(t)).length)!==Object.keys(a).length)return!1;for(u=c;0!=u--;)if(!Object.prototype.hasOwnProperty.call(a,s[u]))return!1;if(r&&t instanceof Element)return!1;for(u=c;0!=u--;)if(("_owner"!==s[u]&&"__v"!==s[u]&&"__o"!==s[u]||!t.$$typeof)&&!e(t[s[u]],a[s[u]]))return!1;return!0}return t!=t&&a!=a}(e,t)}catch(a){if((a.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw a}}}}]); \ No newline at end of file diff --git a/website/site-dist/11fad8c4.4b88cf64.js b/website/site-dist/11fad8c4.4b88cf64.js new file mode 100644 index 0000000000..ef57440476 --- /dev/null +++ b/website/site-dist/11fad8c4.4b88cf64.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{100:function(e,t,r){"use strict";r.r(t),r.d(t,"frontMatter",(function(){return c})),r.d(t,"metadata",(function(){return i})),r.d(t,"rightToc",(function(){return l})),r.d(t,"default",(function(){return s}));var n=r(2),o=r(6),a=(r(0),r(149)),c={id:"talks",title:"Talks and Presentations",sidebar_label:"Talks"},i={id:"talks",isDocsHomePage:!1,title:"Talks and Presentations",description:"Coming soon",source:"@site/docs/talks.md",permalink:"/docs/talks",editUrl:"https://github.com/cloudfoundry/stratos/edit/master/website/docs/talks.md",sidebar_label:"Talks"},l=[],u={rightToc:l};function s(e){var t=e.components,r=Object(o.a)(e,["components"]);return Object(a.b)("wrapper",Object(n.a)({},u,r,{components:t,mdxType:"MDXLayout"}),Object(a.b)("p",null,"Coming soon"))}s.isMDXComponent=!0},149:function(e,t,r){"use strict";r.d(t,"a",(function(){return p})),r.d(t,"b",(function(){return b}));var n=r(0),o=r.n(n);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var u=o.a.createContext({}),s=function(e){var t=o.a.useContext(u),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=s(e.components);return o.a.createElement(u.Provider,{value:t},e.children)},f={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},d=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),p=s(r),d=n,b=p["".concat(c,".").concat(d)]||p[d]||f[d]||a;return r?o.a.createElement(b,i(i({ref:t},u),{},{components:r})):o.a.createElement(b,i({ref:t},u))}));function b(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,c=new Array(a);c[0]=d;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i.mdxType="string"==typeof e?e:n,c[1]=i;for(var u=2;u=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=a.a.createContext({}),b=function(e){var t=a.a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},u=function(e){var t=b(e.components);return a.a.createElement(s.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},p=a.a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,l=e.parentName,s=c(e,["components","mdxType","originalType","parentName"]),u=b(n),p=i,h=u["".concat(l,".").concat(p)]||u[p]||d[p]||r;return n?a.a.createElement(h,o(o({ref:t},s),{},{components:n})):a.a.createElement(h,o({ref:t},s))}));function h(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,l=new Array(r);l[0]=p;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:i,l[1]=o;for(var s=2;s{let n=[],i=[];function c(){const c=function(){let e=0,t=null;for(n=document.getElementsByClassName("anchor");e=0&&r<=a&&(t=l),e+=1}return t}();if(c){let a=0,n=!1;for(i=document.getElementsByClassName(e);a{document.removeEventListener("scroll",c),document.removeEventListener("resize",c)}})},d=a(151),E=a(102),g=a.n(E);function u({headings:e}){return s("table-of-contents__link","table-of-contents__link--active",100),l.a.createElement("div",{className:"col col--3"},l.a.createElement("div",{className:g.a.tableOfContents},l.a.createElement(v,{headings:e})))}function v({headings:e,isChild:t}){return e.length?l.a.createElement("ul",{className:t?"":"table-of-contents table-of-contents__left-border"},e.map(e=>l.a.createElement("li",{key:e.id},l.a.createElement("a",{href:"#"+e.id,className:"table-of-contents__link",dangerouslySetInnerHTML:{__html:e.value}}),l.a.createElement(v,{isChild:!0,headings:e.children})))):null}t.default=function(e){const{siteConfig:t={}}=Object(i.a)(),{url:a,title:n}=t,{content:s}=e,{metadata:E}=s,{description:v,title:p,permalink:h,editUrl:f,lastUpdatedAt:_,lastUpdatedBy:b,version:N,latestVersionMainDocPermalink:w}=E,{frontMatter:{image:k,keywords:y,hide_title:x,hide_table_of_contents:C}}=s,L=p?`${p} | ${n}`:n,O=Object(c.a)(k,{absolute:!0});return l.a.createElement(l.a.Fragment,null,l.a.createElement(r.a,null,l.a.createElement("title",null,L),l.a.createElement("meta",{property:"og:title",content:L}),v&&l.a.createElement("meta",{name:"description",content:v}),v&&l.a.createElement("meta",{property:"og:description",content:v}),y&&y.length&&l.a.createElement("meta",{name:"keywords",content:y.join(",")}),k&&l.a.createElement("meta",{property:"og:image",content:O}),k&&l.a.createElement("meta",{property:"twitter:image",content:O}),k&&l.a.createElement("meta",{name:"twitter:image:alt",content:"Image for "+p}),h&&l.a.createElement("meta",{property:"og:url",content:a+h}),h&&l.a.createElement("link",{rel:"canonical",href:a+h})),l.a.createElement("div",{className:Object(d.a)("container padding-vert--lg",g.a.docItemWrapper)},l.a.createElement("div",{className:"row"},l.a.createElement("div",{className:Object(d.a)("col",{[g.a.docItemCol]:!C})},w&&l.a.createElement("div",{className:"alert alert--warning margin-bottom--md",role:"alert"},"next"===N?l.a.createElement("div",null,"This is unreleased documentation for ",n," ",l.a.createElement("strong",null,N)," version."):l.a.createElement("div",null,"This is archived documentation for ",n," ",l.a.createElement("strong",null,"v",N),", which is no longer actively maintained."),l.a.createElement("div",{className:"margin-top--md"},"For up-to-date documentation, see the"," ",l.a.createElement("strong",null,l.a.createElement(m.a,{to:w},"latest version")),".")),l.a.createElement("div",{className:g.a.docItemContainer},l.a.createElement("article",null,N&&l.a.createElement("div",null,l.a.createElement("span",{className:"badge badge--secondary"},"Version: ",N)),!x&&l.a.createElement("header",null,l.a.createElement("h1",{className:g.a.docTitle},p)),l.a.createElement("div",{className:"markdown"},l.a.createElement(s,null))),(f||_||b)&&l.a.createElement("div",{className:"margin-vert--xl"},l.a.createElement("div",{className:"row"},l.a.createElement("div",{className:"col"},f&&l.a.createElement("a",{href:f,target:"_blank",rel:"noreferrer noopener"},l.a.createElement("svg",{fill:"currentColor",height:"1.2em",width:"1.2em",preserveAspectRatio:"xMidYMid meet",viewBox:"0 0 40 40",style:{marginRight:"0.3em",verticalAlign:"sub"}},l.a.createElement("g",null,l.a.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"}))),"Edit this page")),(_||b)&&l.a.createElement("div",{className:"col text--right"},l.a.createElement("em",null,l.a.createElement("small",null,"Last updated"," ",_&&l.a.createElement(l.a.Fragment,null,"on"," ",l.a.createElement("time",{dateTime:new Date(1e3*_).toISOString(),className:g.a.docLastUpdatedAt},new Date(1e3*_).toLocaleDateString()),b&&" "),b&&l.a.createElement(l.a.Fragment,null,"by ",l.a.createElement("strong",null,b)),!1))))),l.a.createElement("div",{className:"margin-vert--lg"},l.a.createElement(o,{metadata:E})))),!C&&s.rightToc&&l.a.createElement(u,{headings:s.rightToc}))))}}}]); \ No newline at end of file diff --git a/website/site-dist/1b74e361.93d60c98.js b/website/site-dist/1b74e361.93d60c98.js new file mode 100644 index 0000000000..5d29b5c00d --- /dev/null +++ b/website/site-dist/1b74e361.93d60c98.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{103:function(e,t,a){"use strict";a.r(t),a.d(t,"frontMatter",(function(){return i})),a.d(t,"metadata",(function(){return r})),a.d(t,"rightToc",(function(){return c})),a.d(t,"default",(function(){return o}));var n=a(2),l=a(6),b=(a(0),a(149)),i={},r={id:"cf-api-v3",isDocsHomePage:!1,title:"cf-api-v3",description:"Cloud Foundry API v3",source:"@site/docs/cf-api-v3.md",permalink:"/docs/cf-api-v3",editUrl:"https://github.com/cloudfoundry/stratos/edit/master/website/docs/cf-api-v3.md"},c=[{value:"Comparing v2 features to v3",id:"comparing-v2-features-to-v3",children:[{value:"V3 Docs",id:"v3-docs",children:[]},{value:"Entity Relations... include-relations --> include",id:"entity-relations-include-relations----include",children:[]},{value:"Collections - Pagination",id:"collections---pagination",children:[]},{value:"Collections - Sorting",id:"collections---sorting",children:[]},{value:"Collections - Filtering",id:"collections---filtering",children:[]},{value:"Entity Validation",id:"entity-validation",children:[]},{value:"Application State",id:"application-state",children:[]}]},{value:"V3 Availability",id:"v3-availability",children:[]},{value:"Stratos Adoption of v3",id:"stratos-adoption-of-v3",children:[{value:"Blocking Issues",id:"blocking-issues",children:[]},{value:"Frustrating Issues",id:"frustrating-issues",children:[]},{value:"Stratos Tasks",id:"stratos-tasks",children:[]},{value:"Questions",id:"questions",children:[]}]},{value:"v3 Required includes, order_by, filters, missing properties",id:"v3-required-includes-order_by-filters-missing-properties",children:[{value:"/apps",id:"apps",children:[]},{value:"/app/${guid}",id:"appguid",children:[]},{value:"/apps/{guid}/packages",id:"appsguidpackages",children:[]},{value:"/apps/{guid}/processes",id:"appsguidprocesses",children:[]},{value:"/service_bindings (functionality for missing /apps/{guid}/service_bindings only)",id:"service_bindings-functionality-for-missing-appsguidservice_bindings-only",children:[]},{value:"/spaces",id:"spaces",children:[]},{value:"/spaces/${guid}",id:"spacesguid",children:[]},{value:"/routes (functionality for `/spaces/${guid}/routes only)",id:"routes-functionality-for-spacesguidroutes-only",children:[]},{value:"/service_instances (functionality for /spaces/{guid}/service_instances only)",id:"service_instances-functionality-for-spacesguidservice_instances-only",children:[]},{value:"/user_provided_service_instances",id:"user_provided_service_instances",children:[]},{value:"/services",id:"services",children:[]},{value:"/service/${guid}",id:"serviceguid",children:[]},{value:"spaces/${guid}/services",id:"spacesguidservices",children:[]},{value:"services/${guid}/service_plans",id:"servicesguidservice_plans",children:[]},{value:"service_bindings (POST)",id:"service_bindings-post",children:[]},{value:"service_bindings/${guid} (DELETE)",id:"service_bindingsguid-delete",children:[]},{value:"service_bindings",id:"service_bindings",children:[]},{value:"service_bindings/${guid}",id:"service_bindingsguid",children:[]},{value:"service_brokers",id:"service_brokers",children:[]},{value:"service_brokers/{guid}",id:"service_brokersguid",children:[]}]},{value:"v3 Required Features",id:"v3-required-features",children:[{value:"Single 'included` section per request",id:"single-included-section-per-request",children:[]},{value:"included lists",id:"included-lists",children:[]},{value:"order_by values in included entities",id:"order_by-values-in-included-entities",children:[]},{value:"filter values in included",id:"filter-values-in-included",children:[]}]}],d={rightToc:c};function o(e){var t=e.components,a=Object(l.a)(e,["components"]);return Object(b.b)("wrapper",Object(n.a)({},d,a,{components:t,mdxType:"MDXLayout"}),Object(b.b)("h1",{id:"cloud-foundry-api-v3"},"Cloud Foundry API v3"),Object(b.b)("p",null,"See ",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/cf-api-v2-usage"}),"Cloud Foundry API v2 Feature Usage")," for v2 information"),Object(b.b)("ol",null,Object(b.b)("li",{parentName:"ol"},Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"#Comparing-v2-features-to-v3"}),"Comparing v2 features to v3")),Object(b.b)("li",{parentName:"ol"},Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"#V3-Availability"}),"V3 Availability")),Object(b.b)("li",{parentName:"ol"},Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"#Stratos-Adoption-of-v3"}),"Stratos Adoption of v3"))),Object(b.b)("h2",{id:"comparing-v2-features-to-v3"},"Comparing v2 features to v3"),Object(b.b)("h3",{id:"v3-docs"},"V3 Docs"),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"http://v3-apidocs.cloudfoundry.org/"}),"http://v3-apidocs.cloudfoundry.org/")),Object(b.b)("li",{parentName:"ul"},Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/cc-api-v3-style-guide"}),"https://github.com/cloudfoundry/cc-api-v3-style-guide"))),Object(b.b)("h3",{id:"entity-relations-include-relations----include"},"Entity Relations... ",Object(b.b)("inlineCode",{parentName:"h3"},"include-relations")," --\x3e ",Object(b.b)("inlineCode",{parentName:"h3"},"include")),Object(b.b)("p",null,"Previously..."),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"When fetching an entity, any referenced child entity or list of entities were omitted. To have them included the property name was\nprovided in an ",Object(b.b)("inlineCode",{parentName:"li"},"include-relations")," parameter. The covered direct child entities and children of that child entity"),Object(b.b)("li",{parentName:"ul"},"Lists of entities that were bigger than 50 were simply omitted.")),Object(b.b)("p",null,"Now, from my understanding, ..."),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"Child entities (single or lists) are referenced by guid in the parent's ",Object(b.b)("inlineCode",{parentName:"li"},"relationships")," section",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"Pagination of lists is only proposed - ",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/cc-api-v3-style-guide#proposal-pagination-of-related-resources"}),"https://github.com/cloudfoundry/cc-api-v3-style-guide#proposal-pagination-of-related-resources")))),Object(b.b)("li",{parentName:"ul"},"Child entities are also listed, with a url to fetch (like the old ",Object(b.b)("inlineCode",{parentName:"li"},"_url")," property), in the ",Object(b.b)("inlineCode",{parentName:"li"},"links")," section."),Object(b.b)("li",{parentName:"ul"},"An ",Object(b.b)("inlineCode",{parentName:"li"},"include")," parameter can be supplied which will add an ",Object(b.b)("inlineCode",{parentName:"li"},"included")," section to the entity"),Object(b.b)("li",{parentName:"ul"},"An entity in the ",Object(b.b)("inlineCode",{parentName:"li"},"included")," section is in the same format as the parent"),Object(b.b)("li",{parentName:"ul"},Object(b.b)("inlineCode",{parentName:"li"},"include")," has very limited implementation",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},Object(b.b)("inlineCode",{parentName:"li"},"/apps")," only supports ",Object(b.b)("inlineCode",{parentName:"li"},"space")," include"),Object(b.b)("li",{parentName:"ul"},Object(b.b)("inlineCode",{parentName:"li"},"/organization")," doesn't support any includes"),Object(b.b)("li",{parentName:"ul"},Object(b.b)("inlineCode",{parentName:"li"},"/space")," doesn't support any includes"),Object(b.b)("li",{parentName:"ul"},"(see ",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"/docs/cf-api-v2-usage#Inline-Relations"}),"Cloud Foundry API v2 Feature Usage - Inline-Relations")," for required)\n~- Unclear if ",Object(b.b)("inlineCode",{parentName:"li"},"include")," will cover chained entities aka ",Object(b.b)("inlineCode",{parentName:"li"},"inline-relations-depth")," from v2~")))),Object(b.b)("h3",{id:"collections---pagination"},"Collections - Pagination"),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"This is covered just fine (fetch a specific page, total page count, total result count, etc)")),Object(b.b)("h3",{id:"collections---sorting"},"Collections - Sorting"),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"It looks like all entities can be sorted via ",Object(b.b)("inlineCode",{parentName:"li"},"created_at")," and ",Object(b.b)("inlineCode",{parentName:"li"},"updated_at")," dates, plus some also have ",Object(b.b)("inlineCode",{parentName:"li"},"name"),". Given that v2 really only\nsupported sorting by ",Object(b.b)("inlineCode",{parentName:"li"},"created_at")," date this should be fine for feature parity"),Object(b.b)("li",{parentName:"ul"},"However in order for Stratos to leave behind local sorting there are many missing sort fields (see ",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"/docs/cf-api-v2-usage#sortingfiltering"}),"Cloud Foundry API v2 Feature Usage - Sorting/Filtering"),")")),Object(b.b)("h3",{id:"collections---filtering"},"Collections - Filtering"),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"Similar level of filtering is available with the addition of ",Object(b.b)("inlineCode",{parentName:"li"},"name")),Object(b.b)("li",{parentName:"ul"},"In order for Stratos to leave behind local filtering there are still some fields that need to be implemented (see ",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"/docs/cf-api-v2-usage#sortingfiltering"}),"Cloud Foundry API v2 Feature Usage - Sorting/Filtering"),")")),Object(b.b)("h3",{id:"entity-validation"},"Entity Validation"),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"For v2 info see ",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"/docs/cf-api-v2-usage#entity-relations--validation"}),"Cloud Foundry API v2 Feature Usage - Entity Relations & Validation")),Object(b.b)("li",{parentName:"ul"},"It looks like, given that ",Object(b.b)("inlineCode",{parentName:"li"},"include")," is considerable beefed up, this will still be possible in v3. An update of the entity relations\nprocess will be required though.")),Object(b.b)("h3",{id:"application-state"},"Application State"),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"For v2 info see ",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"/docs/cf-api-v2-usage#Application-State"}),"Cloud Foundry API v2 Feature Usage - Application State")),Object(b.b)("li",{parentName:"ul"},"The improved application state string that stratos shows will be much harder to determine",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"App ",Object(b.b)("inlineCode",{parentName:"li"},"package_state")," is from a separate entity that is not ",Object(b.b)("inlineCode",{parentName:"li"},"linked")," and requires an additional request"),Object(b.b)("li",{parentName:"ul"},"App ",Object(b.b)("inlineCode",{parentName:"li"},"package_updated_at")," is from a separate entity that is not ",Object(b.b)("inlineCode",{parentName:"li"},"linked")," and requires an additional request"),Object(b.b)("li",{parentName:"ul"},"App instance state should now come form ",Object(b.b)("inlineCode",{parentName:"li"},"/processes")," and given that instance:process are now not 1:1 harder to summaries state from")))),Object(b.b)("h2",{id:"v3-availability"},"V3 Availability"),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"Stratos needs to support cloud foundry's with different api versions from many different providers and epochs"),Object(b.b)("li",{parentName:"ul"},"Update, many common CFs we use support some kind of v3 version.",Object(b.b)("blockquote",{parentName:"li"},Object(b.b)("p",{parentName:"blockquote"},"Note - cf-dev I haven't tested as it's unsupported on linux - see ",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry-incubator/cfdev/issues/18"}),"https://github.com/cloudfoundry-incubator/cfdev/issues/18")," (major regression from PCFDev there)"))),Object(b.b)("li",{parentName:"ul"},Object(b.b)("del",{parentName:"li"},"Currently, it looks like neither SCF (2.84.0), IBM Cloud (2.106.0) or PCFDev (2.82.0) support v3 with ",Object(b.b)("inlineCode",{parentName:"del"},"includes"),". PWS (2.125.0) and\nSAP (2.120.0) however do."),Object(b.b)("blockquote",{parentName:"li"},Object(b.b)("p",{parentName:"blockquote"},"Note - ",Object(b.b)("del",{parentName:"p"},"Couldn't find an easy way to determine the version of v3"))))),Object(b.b)("h2",{id:"stratos-adoption-of-v3"},"Stratos Adoption of v3"),Object(b.b)("p",null,"Given that..."),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"Endpoints are being converted to v3 iteratively, not all are available at the moment"),Object(b.b)("li",{parentName:"ul"},"Stratos will need to support v2 for a while to come (legacy installs, etc)")),Object(b.b)("p",null,"Then Stratos should either .."),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"Wait until v3 has feature parity with v2, create new Stratos that uses v3 and mothball versions of Stratos that talk to v2"),Object(b.b)("li",{parentName:"ul"},"Support both versions at runtime, switching each endpoint from v2 to v3 at determined cut off dates")),Object(b.b)("h3",{id:"blocking-issues"},"Blocking Issues"),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"Coverage of ",Object(b.b)("inlineCode",{parentName:"li"},"include")," is not on par with v2 ",Object(b.b)("inlineCode",{parentName:"li"},"include-relations"),Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"To meet parity it should support all entities in ",Object(b.b)("inlineCode",{parentName:"li"},"relationships")," and ",Object(b.b)("inlineCode",{parentName:"li"},"links"),", whether one to one or one to many"),Object(b.b)("li",{parentName:"ul"},"Currently not supported on all endpoints and does not cover enough ",Object(b.b)("inlineCode",{parentName:"li"},"relationships"),"/",Object(b.b)("inlineCode",{parentName:"li"},"links")," (see ",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"/docs/cf-api-v2-usage#Inline-Relations"}),"Cloud Foundry API v2 Feature Usage - Inline-Relations"),")"),Object(b.b)("li",{parentName:"ul"},"For instance new v3 entities are not ",Object(b.b)("inlineCode",{parentName:"li"},"include"),"s (",Object(b.b)("inlineCode",{parentName:"li"},"/apps")," - ",Object(b.b)("inlineCode",{parentName:"li"},"package"),", ",Object(b.b)("inlineCode",{parentName:"li"},"processes"),", ",Object(b.b)("inlineCode",{parentName:"li"},"route_mappings"),", ",Object(b.b)("inlineCode",{parentName:"li"},"environment_variables"),", ",Object(b.b)("inlineCode",{parentName:"li"},"droplets"),", ",Object(b.b)("inlineCode",{parentName:"li"},"tasks"),")"),Object(b.b)("li",{parentName:"ul"},Object(b.b)("del",{parentName:"li"},"Not supported by common CFs used to develop with (SCF, PCFDev)"),"."))),Object(b.b)("li",{parentName:"ul"},"Entities do not contain all properties that were in v2 (where functionality has not changed)",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"Covers simple values and entities (one to one and one to many)"),Object(b.b)("li",{parentName:"ul"},"For instance ",Object(b.b)("inlineCode",{parentName:"li"},"/organizations")," and ",Object(b.b)("inlineCode",{parentName:"li"},"/spaces")," endpoints are not completed and contain only guid, create/updated date and name (space additionally has experimental ",Object(b.b)("inlineCode",{parentName:"li"},"organization"),") "))),Object(b.b)("li",{parentName:"ul"},"Entities returned by v2/v3 endpoints are not consistent",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"For example",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"push an app with ",Object(b.b)("inlineCode",{parentName:"li"},"v3-push")," and it shows up in ",Object(b.b)("inlineCode",{parentName:"li"},"v2/apps")),Object(b.b)("li",{parentName:"ul"},Object(b.b)("inlineCode",{parentName:"li"},"v3/service_bindings")," does not return service bindings that aren't attached to a v3 app"))),Object(b.b)("li",{parentName:"ul"},"Without knowing exactly all these occurrences we won't be able to work in a mixed v2/v3 endpoint state"))),Object(b.b)("li",{parentName:"ul"},Object(b.b)("del",{parentName:"li"},"Cannot determine if a CF supports v3 or when it does support v3 which endpoints it has"),Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"v3 version and supported endpoints can be determined by response to ",Object(b.b)("inlineCode",{parentName:"li"},"")," and ",Object(b.b)("inlineCode",{parentName:"li"},"/v3")),Object(b.b)("li",{parentName:"ul"},Object(b.b)("del",{parentName:"li"},"Getting the v2 version is simple, I don't know if there's correlation to v3 version")),Object(b.b)("li",{parentName:"ul"},Object(b.b)("del",{parentName:"li"},"Having a v3/info which published which endpoints are supported would help a lot. Including whether ",Object(b.b)("inlineCode",{parentName:"del"},"include")," is supported")))),Object(b.b)("li",{parentName:"ul"},Object(b.b)("del",{parentName:"li"},"Chained ",Object(b.b)("inlineCode",{parentName:"del"},"links"),"/relations don't appear to be supported (fetch app--\x3espace--\x3eorg all in one request)"),Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"It looks like this is achievable by notation, for example ",Object(b.b)("inlineCode",{parentName:"li"},"/v3/apps?include=space,space.organization")),Object(b.b)("li",{parentName:"ul"},"See ",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/cc-api-v3-style-guide#including-related-resources"}),"https://github.com/cloudfoundry/cc-api-v3-style-guide#including-related-resources")),Object(b.b)("li",{parentName:"ul"},Object(b.b)("del",{parentName:"li"},"Might be wrong on this one due to the lack of current ",Object(b.b)("inlineCode",{parentName:"del"},"include")," integration"))))),Object(b.b)("h3",{id:"frustrating-issues"},"Frustrating Issues"),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"Fetching a list of users as a non-cf admin involves making a request to every organisation (",Object(b.b)("inlineCode",{parentName:"li"},"organization/${guid}/users"),"). The response\nof all of these calls contains a lot of overlapping data",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"Ideally making a request to ",Object(b.b)("inlineCode",{parentName:"li"},"/users")," as a user with 0:M org roles would return a list of users in those organisations"),Object(b.b)("li",{parentName:"ul"},"Have asked this question in the V3 Users proposal - ",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.tyy5zdgqnnt0"}),"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.tyy5zdgqnnt0")))),Object(b.b)("li",{parentName:"ul"},"Not all v2 endpoints exist in v3, for instance no ",Object(b.b)("inlineCode",{parentName:"li"},"domains"),", ",Object(b.b)("inlineCode",{parentName:"li"},"events"),", ",Object(b.b)("inlineCode",{parentName:"li"},"route"),", org/space quota definitions, etc",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"This would make our entity validation much more complex"))),Object(b.b)("li",{parentName:"ul"},"Cannot utilise v3 pagination due to limited sorting and filtering functionality (see ",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"/docs/cf-api-v2-usage#sortingFiltering"}),"Cloud Foundry API v2 Feature Usage - Sorting/Filtering")," for missing fields)",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"This is currently on par with v2, but causes us a lot of headaches for large data sets"))),Object(b.b)("li",{parentName:"ul"},"The Stratos method of calculating application state has become much harder",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"Additional requests to app ",Object(b.b)("inlineCode",{parentName:"li"},"/packages")," are required. This would be resolved if applications were ",Object(b.b)("inlineCode",{parentName:"li"},"link"),"ed to package"),Object(b.b)("li",{parentName:"ul"},"Would love a flag in ",Object(b.b)("inlineCode",{parentName:"li"},"/apps")," to also return the ",Object(b.b)("inlineCode",{parentName:"li"},"processes")," data. This would mean a longer request time, but we're making that request\nin the frontend anyway."))),Object(b.b)("li",{parentName:"ul"},"No easy way to fetch organisation or space summary information",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"Stratos show summary information such as number of users (see ",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"/docs/cf-api-v2-usage#cloud-foundry-organisation-and-space-summary-information"}),"Cloud Foundry API v2 Feature Usage V2 Specifics - Cloud Foundry, Organisation and Space Summary Information")," for specific stats)"),Object(b.b)("li",{parentName:"ul"},"In an ideal world we could hit one endpoint that would give us the counts for all of these details. Filters could then limit this to\nan organisation or space")))),Object(b.b)("h3",{id:"stratos-tasks"},"Stratos Tasks"),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"Depending on adoption approach, Stratos needs to support v2 and v3 endpoints concurrently",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"Mask the input/output to v3 requests, such that store, pagination, list configuration and entity validation remains mostly unchanged"),Object(b.b)("li",{parentName:"ul"},"To do this ...",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"Query params need to be converted when making v3 requests"),Object(b.b)("li",{parentName:"ul"},"v3 responses need to be converted into v2 format (entity/metadata, ",Object(b.b)("inlineCode",{parentName:"li"},"_url"),", etc)."))))),Object(b.b)("li",{parentName:"ul"},"Update application deploy/lifecycle process to match new v3 process (",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/3150"}),"https://github.com/cloudfoundry/stratos/issues/3150"),")"),Object(b.b)("li",{parentName:"ul"},"Support new 'processes' concept (",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/3154"}),"https://github.com/cloudfoundry/stratos/issues/3154"),"), including updating how\nwe determine application state"),Object(b.b)("li",{parentName:"ul"},"Fully investigate non ",Object(b.b)("inlineCode",{parentName:"li"},"get")," methods (create an application, delete a space, etc)"),Object(b.b)("li",{parentName:"ul"},"Related Issues",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2922"}),"https://github.com/cloudfoundry/stratos/issues/2922")),Object(b.b)("li",{parentName:"ul"},Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/3149"}),"https://github.com/cloudfoundry/stratos/issues/3149")," (Container issue for related v3 api process changes)")))),Object(b.b)("h3",{id:"questions"},"Questions"),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},Object(b.b)("del",{parentName:"li"},"Will ",Object(b.b)("inlineCode",{parentName:"del"},"include")," cover children of children? For instance ",Object(b.b)("inlineCode",{parentName:"del"},"app")," --\x3e ",Object(b.b)("inlineCode",{parentName:"del"},"route")," --\x3e ",Object(b.b)("inlineCode",{parentName:"del"},"domain")),Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},Object(b.b)("del",{parentName:"li"},"How will lists be covered? For instance ",Object(b.b)("inlineCode",{parentName:"del"},"organization")," --\x3e ",Object(b.b)("inlineCode",{parentName:"del"},"space")," --\x3e ",Object(b.b)("inlineCode",{parentName:"del"},"service instances"))))),Object(b.b)("li",{parentName:"ul"},"How will the deprecation of v2 endpoints happen?",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"One by one?"),Object(b.b)("li",{parentName:"ul"},"All together once v2 parity is reached?"))),Object(b.b)("li",{parentName:"ul"},"Will duplicated ",Object(b.b)("inlineCode",{parentName:"li"},"include"),"ed entities only appear once in a top level (entity or pagination) ",Object(b.b)("inlineCode",{parentName:"li"},"included"),"? For example..conceptually..",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"Fetch an application, the application's space, the application's routes and application routes spaces all in a single request"),Object(b.b)("li",{parentName:"ul"},"If the application's space appeared in the route's space, would it only appear once in the application's",Object(b.b)("inlineCode",{parentName:"li"},"included")," section... or appear twice (once\nin application ",Object(b.b)("inlineCode",{parentName:"li"},"included")," and again in route ",Object(b.b)("inlineCode",{parentName:"li"},"included"),")?"))),Object(b.b)("li",{parentName:"ul"},"The style guide references a way to fetch one to many relationships as ",Object(b.b)("inlineCode",{parentName:"li"},"/v3/apps/:app_guid/relationships/routes")," (",Object(b.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/cc-api-v3-style-guide#viewing-1"}),"https://github.com/cloudfoundry/cc-api-v3-style-guide#viewing-1"),")",Object(b.b)("ul",{parentName:"li"},Object(b.b)("li",{parentName:"ul"},"This doesn't seem to work (404), is it yet to be implemented?"),Object(b.b)("li",{parentName:"ul"},Object(b.b)("inlineCode",{parentName:"li"},"/v3/apps/:app_guid/routes")," also does not work (404)"),Object(b.b)("li",{parentName:"ul"},Object(b.b)("inlineCode",{parentName:"li"},"/v3/apps/:app_guid/route_mappings")," works, but there doesn't seem to be a way to ",Object(b.b)("inlineCode",{parentName:"li"},"include")," the ",Object(b.b)("inlineCode",{parentName:"li"},"route")," such that it appears in the response"))),Object(b.b)("li",{parentName:"ul"},"Which version is the ",Object(b.b)("inlineCode",{parentName:"li"},"include=space,space.organization")," notation supported in?")),Object(b.b)("h2",{id:"v3-required-includes-order_by-filters-missing-properties"},"v3 Required ",Object(b.b)("inlineCode",{parentName:"h2"},"include"),"s, ",Object(b.b)("inlineCode",{parentName:"h2"},"order_by"),", filters, missing properties"),Object(b.b)("p",null,"A few UX examples have been provided, however it's quite hard to list all requirements without a deep dive into the code. Most requirements\nfor existing endpoints come from the need to either .."),Object(b.b)("ul",null,Object(b.b)("li",{parentName:"ul"},"Fetch properties, properties of properties, etc inline instead of making additional request. For the application wall's application list\nthis can be the difference between making 21 calls and then a subsequent 18 calls.. rather than receive everything with the apps request."),Object(b.b)("li",{parentName:"ul"},"Switch from a local list (sorting and filtering done locally due to lack of support in v2) to a non-local list (pagination, sorting and\nfiltering done via v3 api)")),Object(b.b)("h3",{id:"apps"},Object(b.b)("inlineCode",{parentName:"h3"},"/apps")),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"include"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"space"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Organization via ",Object(b.b)("inlineCode",{parentName:"td"},"space.organization")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Used in application wall's application list to filter local lists by org, show org name on app wall app entries, upfront fetch leading to quicker navigation to app summary"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See (",Object(b.b)("a",Object(n.a)({parentName:"td"},{href:"/docs/cf-api-v2-usage#Lists"}),"non-local lists")," for more detail on local and non-local lists).")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"packages")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Required to determine application state (state, updated_at)")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"processes")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Required to determine application state (instances)")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Stats via ",Object(b.b)("inlineCode",{parentName:"td"},"processes.stats")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Required to determine application state (state).")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"current_droplet")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Required to determine application state (state).")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Builds via ",Object(b.b)("inlineCode",{parentName:"td"},"packages.builds")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"v3 currently has no link or relation. Required to determine application state (state).")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"sum of ",Object(b.b)("inlineCode",{parentName:"td"},"processes")," ",Object(b.b)("inlineCode",{parentName:"td"},"instances")," count ",Object(b.b)("a",Object(n.a)({parentName:"td"},{href:"#v3-Required-Features"}),"See below for notes")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"sum of ",Object(b.b)("inlineCode",{parentName:"td"},"processes")," ",Object(b.b)("inlineCode",{parentName:"td"},"disk_in_mb")," count ",Object(b.b)("a",Object(n.a)({parentName:"td"},{href:"#v3-Required-Features"}),"See below for notes")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"sum of ",Object(b.b)("inlineCode",{parentName:"td"},"processes")," ",Object(b.b)("inlineCode",{parentName:"td"},"memory_in_mb")," count ",Object(b.b)("a",Object(n.a)({parentName:"td"},{href:"#v3-Required-Features"}),"See below for notes")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"processes")," state"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"User wishes to find all apps that have errored processes"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"organization name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[3]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"space name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[3]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))))),Object(b.b)("p",null,"[1]"," Property/s used to determine application state without spamming requests (",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"#Application-State"}),"app state"),"). On the application wall\npage we determine the state of up to 9 apps at a time. Returning this information in a single request, or during the initial request, will\nsave apps x missing property's endpoints (packages, process, process stats, current_droplet, etc). This could lead to 21 concurrent calls\nfollowed by another 18 (given the results of the first run)."),Object(b.b)("p",null,"[2]"," Enables sorting by instance count in tables. See (",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/cf-api-v2-usage#Lists"}),"non-local lists")," for more information on local and non-local list sorting)."),Object(b.b)("p",null,"[3]"," Allows free text search by org or space name in application wall (rather than manual selection of cf, org and then space). For instance a user types part of an org name in a\nspecial org drop down and is presented with list of apps in matching orgs. This is a short cut for the user having to scroll down a list in a\ndrop down."),Object(b.b)("h3",{id:"appguid"},Object(b.b)("inlineCode",{parentName:"h3"},"/app/${guid}")),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"route_mappings")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Route via ",Object(b.b)("inlineCode",{parentName:"td"},"route_mappings.route")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]",". ",Object(b.b)("inlineCode",{parentName:"td"},"/route")," has no v3 equivalent")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Domain via ",Object(b.b)("inlineCode",{parentName:"td"},"route_mappings.route.domain")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]",". ",Object(b.b)("inlineCode",{parentName:"td"},"/domain")," has no v3 equivalent. Required to display complete route url. From Greg ",Object(b.b)("inlineCode",{parentName:"td"},"We are thinking about adding a fqdn on the routes object, which may be another way to achieve the same objective."))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_bindings")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[3]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_bindings")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[3]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"include"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"space"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"space.organization")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display the name of the organisation"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"packages")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[4]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]",". Required to determine application state (state, updated_at)")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"processes")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[4]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]",". Required to determine app state (instances)")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"processes.stats")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[4]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]",". Required to determine app state (state).")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"current_droplet")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[4]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]",". Required to determine app state (state).")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"packages.builds")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[4]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]",". v3 currently has no link or relation. Required to determine app state (state).")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"features")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display current app settings (ssh enabled and revisions enabled)."),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]",". There's a top level ssh enabled flag, however this will show if at the app level ssh is enabled")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"features")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"droplets")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"We don't currently use this, however displaying these in a list to the user would be beneficial."),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"tasks")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"We don't currently use this, however displaying these in a list to the user would be beneficial."),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},"property")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},"stack guid/whole entity")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Stack name is included inline in an inlined ",Object(b.b)("inlineCode",{parentName:"td"},"lifecycle")," object. This placement seems like an odd pattern. It's not an entity on it's own with it's own endpoint... but does contain an inline entity (stack). The inlined stack contains only a name and not guid/rest of stack entity. From Greg ",Object(b.b)("inlineCode",{parentName:"td"},"Stack is referenced by name rather than guid due to some windows usage patterns. The window's stacks are not associated with a rootfs like the linux ones are, so they can add new stacks without having to update the stacks of all windows apps."),".")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},"property")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},"buildpack guid/whole entity")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"As per stack guid above. From Greg ",Object(b.b)("inlineCode",{parentName:"td"},"Similarly with buildpacks, having associations by name rather than guid allows for upgrades across stack versions (for example the recent upgrade from cflinuxfs2 -> cflinuxfs3) without having to re-associated apps with the new stack's version of the buildpack."))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},"property")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"enable_ssh"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},".. or similar property to determine if ssh'ing to an instance is allowed at the app level"),". See ",Object(b.b)("inlineCode",{parentName:"td"},"/v3/apps/:guid/ssh_enabled"))))),Object(b.b)("p",null,"[1]"," Display bound route count & list of routes"),Object(b.b)("p",null,"[2]"," Display information quicker on the Application pages without having to make additional requests (either once for a single entity or\nmultiple times in the case of 1:M, for example ",Object(b.b)("inlineCode",{parentName:"p"},"route_mappings")," would require multiple requests to ",Object(b.b)("inlineCode",{parentName:"p"},"routes")," to fetch each one)"),Object(b.b)("p",null,"[3]"," Display bound service instance count & list of services, determine if a service is already bound when user is binding existing service to app, etc"),Object(b.b)("p",null,"[4]"," Property/s used to determine application state without spamming endpoints (",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"#Application-State"}),"app state"),")."),Object(b.b)("h3",{id:"appsguidpackages"},Object(b.b)("inlineCode",{parentName:"h3"},"/apps/{guid}/packages")),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"builds")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See explanation in ",Object(b.b)("inlineCode",{parentName:"td"},"/app/${guid}")," - ",Object(b.b)("inlineCode",{parentName:"td"},"packages.builds")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"builds")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"app")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[LOW]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"This might come in handy in the future, more specifically if we list all ",Object(b.b)("inlineCode",{parentName:"td"},"packages")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))))),Object(b.b)("p",null,"[1]"," If at some point we've fetched an app without this property we will make a separate request to fetch it, so the same includes/links are required"),Object(b.b)("h3",{id:"appsguidprocesses"},Object(b.b)("inlineCode",{parentName:"h3"},"/apps/{guid}/processes")),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"stats")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See explanation in ",Object(b.b)("inlineCode",{parentName:"td"},"/app/${guid}")," - ",Object(b.b)("inlineCode",{parentName:"td"},"processes.stats")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"state")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"In the app summary page instances tab we show a list of instances and their properties. This needs updating, but it's easy to imagine that we will display a list of processes in v3"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"stats")," ",Object(b.b)("inlineCode",{parentName:"td"},"usage.time")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2][See below for notes]","(#v3-Required-Features)")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"stats")," ",Object(b.b)("inlineCode",{parentName:"td"},"usage.cpu")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2][See below for notes]","(#v3-Required-Features)")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"stats")," ",Object(b.b)("inlineCode",{parentName:"td"},"usage.mem")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2][See below for notes]","(#v3-Required-Features)")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"stats")," ",Object(b.b)("inlineCode",{parentName:"td"},"usage.disk")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2][See below for notes]","(#v3-Required-Features)")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"state")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))))),Object(b.b)("p",null,"[1]"," If at some point we've fetched an app without this property we will make a separate request to fetch it, so the same includes/links are required"),Object(b.b)("p",null,"[2]"," This will be required in order to switch from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/cf-api-v2-usage#Lists"}),"non-local lists")," for more detail on local and non-local lists."),Object(b.b)("h3",{id:"service_bindings-functionality-for-missing-appsguidservice_bindings-only"},Object(b.b)("inlineCode",{parentName:"h3"},"/service_bindings")," (functionality for missing /apps/{guid}/service_bindings only)"),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instance")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instance")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instance.service")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instance.service")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instance.service_plan")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instance.service_plan")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instance.tags")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instance.tags")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"service instance name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[3]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"service name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"service plan name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"service instance name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"service name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"service plan name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")))),Object(b.b)("p",null,"[1]"," Display a list of service instances associated with a specific application"),Object(b.b)("p",null,"[2]"," Fetching this information inline avoids making lots of additional requests"),Object(b.b)("p",null,"[3]"," This will be required in order to switch from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/cf-api-v2-usage#Lists"}),"non-local lists")," for more detail on local and non-local lists)."),Object(b.b)("h3",{id:"spaces"},Object(b.b)("inlineCode",{parentName:"h3"},"/spaces")),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instances")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[LOW]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Show the count of service instances in the space"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"In the medium to long term we will determine this another way")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instances")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[LOW]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"space_quota_definition")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display the space quota information information per space"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[3]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"space_quota_definition")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"include"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"applications"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Previous requirement pre-scaling change")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"created_at")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"name")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]",". Pre-check to ensure a space name is not taken before attempting to create."),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]")))),Object(b.b)("p",null,"[1]"," Display a list of spaces in an organisation"),Object(b.b)("p",null,"[2]"," This will be required in order to switch from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/cf-api-v2-usage#Lists"}),"non-local lists")," for more detail on local and non-local lists)."),Object(b.b)("p",null,"[3]"," Avoids making additional requests. Particularly important when viewing multiple spaces at the same time."),Object(b.b)("h3",{id:"spacesguid"},Object(b.b)("inlineCode",{parentName:"h3"},"/spaces/${guid}")),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"organization")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Basic location information, display name and other information"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Avoids making additional requests")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"organization")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"domains")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Efficiency request, better to get these here than separately"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"/domains")," has no v3 equivalent")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"domains")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"routes")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[LOW]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display the number of routes in this organisation"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"/routes")," has no v3 equivalent. See ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"routes")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[LOW]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},"links")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"routes.domain"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Depending on the list of routes is bad due to scaling. We're removing this functionality")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"include"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"routes.domain"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},"links")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"routes.applications"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"include"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"routes.applications"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"include"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"applications"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Previous requirement pre-scaling change")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instances")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[LOW]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display the number of service instances in this organisation"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instances")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[LOW]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},"links")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"service_instances.service_bindings"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Depending on the list of service instances is bad due to scaling. We're removing this functionality")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},"`include"),"`"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("del",{parentName:"td"},Object(b.b)("inlineCode",{parentName:"del"},"service_instances.service_bindings"))),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"space quota"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display quota information, when possible how close user is to various quotas, etc"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"space quota has no v3 equivalent")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"space quota"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"property"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"allow_ssh"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display value to user. Important from an admin sense"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"space.developers")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"we might be able to fetch this via new users endpoints described in ",Object(b.b)("a",Object(n.a)({parentName:"td"},{href:"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"}),"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"space.developers")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"we might be able to fetch this via new users endpoints described in ",Object(b.b)("a",Object(n.a)({parentName:"td"},{href:"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"}),"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"space.managers")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"we might be able to fetch this via new users endpoints described in ",Object(b.b)("a",Object(n.a)({parentName:"td"},{href:"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"}),"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"space.managers")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"we might be able to fetch this via new users endpoints described in ",Object(b.b)("a",Object(n.a)({parentName:"td"},{href:"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"}),"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"space.auditors")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"we might be able to fetch this via new users endpoints described in ",Object(b.b)("a",Object(n.a)({parentName:"td"},{href:"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"}),"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"space.auditors")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"we might be able to fetch this via new users endpoints described in ",Object(b.b)("a",Object(n.a)({parentName:"td"},{href:"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"}),"https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj"))))),Object(b.b)("p",null,"[1]"," Pre-scaling change. We just want the total count of entities. In the medium to long term we will determine this another way"),Object(b.b)("p",null,"[2]"," Display a list of users and their roles"),Object(b.b)("h3",{id:"routes-functionality-for-spacesguidroutes-only"},Object(b.b)("inlineCode",{parentName:"h3"},"/routes")," (functionality for `/spaces/${guid}/routes only)"),Object(b.b)("blockquote",null,Object(b.b)("p",{parentName:"blockquote"},"Note - There doesn't seem to be a way to list routes in a space. This is separate to the concept of listing them inline in a space (with\nsome overlap though). This endpoint would be used to fetch a list of routes for a specific space and display them to the user.\nThe ",Object(b.b)("inlineCode",{parentName:"p"},"/v3/route_mappings")," endpoint provides a way to search for routes by app or route but not by space.")),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"space guid"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display a list of routes that are in a space"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"domain")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[LOW]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display the url of the route"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Not required if the fqdn is returned in the base route")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"domain")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[LOW]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"links"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"applications")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display a list of the apps that are bound to the route"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Avoids making a request to ",Object(b.b)("inlineCode",{parentName:"td"},"/v3/route_mappings")," for each route (could be a massive amount). We expect these relations to be 1-to-not-many")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"applications")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")))),Object(b.b)("h3",{id:"service_instances-functionality-for-spacesguidservice_instances-only"},Object(b.b)("inlineCode",{parentName:"h3"},"/service_instances")," (functionality for /spaces/{guid}/service_instances only)"),Object(b.b)("blockquote",null,Object(b.b)("p",{parentName:"blockquote"},"There's lots more that could be added here when taking into account our service instance lists in places other than the space details page\n(mainly including space and space.organisation).")),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"link"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instance.applications")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display bound applications in a list of service instances"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Not sure if this will be implemented the same as routes and route mappings, but would need similar functionality to fetch list inline. This could be replaced with a link to ",Object(b.b)("inlineCode",{parentName:"td"},"service_bindings")," and then the ",Object(b.b)("inlineCode",{parentName:"td"},"app")," for that binding")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_instance.applications")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"link"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_plan")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display service plan information per SI in a list of SI"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]",". ",Object(b.b)("inlineCode",{parentName:"td"},"/service_plan")," has no v3 equivalent")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_plan")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"link"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Display service information per SI in a list of SI"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[2]"," ",Object(b.b)("inlineCode",{parentName:"td"},"/service")," has no v3 equivalent")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"space guid"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[3]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"org guid"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[3]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"name")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[3]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"space"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"When showing all SI in a CF fetch inlined space to space name and allow local filtering by space and org"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))))),Object(b.b)("p",null,"[1]"," Display list of service instances in a space"),Object(b.b)("p",null,"[2]"," Avoids making additional requests per service instance"),Object(b.b)("p",null,"[3]"," This will be required in order to switch from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/cf-api-v2-usage#Lists"}),"non-local lists")," for more detail on local and non-local lists)."),Object(b.b)("h3",{id:"user_provided_service_instances"},Object(b.b)("inlineCode",{parentName:"h3"},"/user_provided_service_instances")),Object(b.b)("p",null,"We've recently integrated user provided service instances into Stratos. There doesn't seem to be any current support for this in v3. We'd\nneed similar functionality to ",Object(b.b)("inlineCode",{parentName:"p"},"/service_instances")," (where there's cross over)."),Object(b.b)("h3",{id:"services"},Object(b.b)("inlineCode",{parentName:"h3"},"/services")),Object(b.b)("blockquote",null,Object(b.b)("p",{parentName:"blockquote"},"Comparison of missing functionality as per proposed spec in ",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"https://docs.google.com/document/d/1bDsEiZRwQJNUI41cQlUaioaY7JA1fnv_AThOI2ekPXNM/edit#"}),"https://docs.google.com/document/d/1bDsEiZRwQJNUI41cQlUaioaY7JA1fnv_AThOI2ekPXNM/edit#"),"\nFor simplicity have kept the ",Object(b.b)("inlineCode",{parentName:"p"},"services")," name instead of the proposed new name of ",Object(b.b)("inlineCode",{parentName:"p"},"service_offerings"))),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"link"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service.service_plans")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Show a count of service plans for a service when showing a list of services"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Depends on implementation of 'included' pagination - see ",Object(b.b)("a",Object(n.a)({parentName:"td"},{href:"https://github.com/cloudfoundry/cc-api-v3-style-guide#proposal-pagination-of-related-resources"}),"https://github.com/cloudfoundry/cc-api-v3-style-guide#proposal-pagination-of-related-resources"))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service.service_plans")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"link"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service.service_broker")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Not currently used, but would be very nice to display the broker where a service is coming from"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Note - whole service broker entity (not just name), would be nice")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service.service_broker")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"name")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"name")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"see ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"active")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"see ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"bindable")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"see ","[1]")))),Object(b.b)("p",null,"[1]"," As other situations where we fetch lists this will help us from switching from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/cf-api-v2-usage#Lists"}),"non-local lists")," for more detail on local and non-local lists)."),Object(b.b)("h3",{id:"serviceguid"},Object(b.b)("inlineCode",{parentName:"h3"},"/service/${guid}")),Object(b.b)("p",null,"See ",Object(b.b)("inlineCode",{parentName:"p"},"/services")," above"),Object(b.b)("h3",{id:"spacesguidservices"},Object(b.b)("inlineCode",{parentName:"h3"},"spaces/${guid}/services")),Object(b.b)("p",null,"To be replaced with ",Object(b.b)("inlineCode",{parentName:"p"},"/services")),Object(b.b)("h3",{id:"servicesguidservice_plans"},Object(b.b)("inlineCode",{parentName:"h3"},"services/${guid}/service_plans")),Object(b.b)("p",null,"Currently missing in v3 docs. If implemented would need the same link/includes as ",Object(b.b)("inlineCode",{parentName:"p"},"service_bindings")," section below"),Object(b.b)("h3",{id:"service_bindings-post"},Object(b.b)("inlineCode",{parentName:"h3"},"service_bindings")," (POST)"),Object(b.b)("p",null,"This looks good"),Object(b.b)("h3",{id:"service_bindingsguid-delete"},Object(b.b)("inlineCode",{parentName:"h3"},"service_bindings/${guid}")," (DELETE)"),Object(b.b)("p",null,"This looks good"),Object(b.b)("h3",{id:"service_bindings"},Object(b.b)("inlineCode",{parentName:"h3"},"service_bindings")),Object(b.b)("p",null,"We don't currently use this, but in order for us to we would need the following"),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_binding.service_instance")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_binding.app")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"service instance name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"application name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"service instance name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"see ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"application name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"see ","[1]")))),Object(b.b)("p",null,"[1]"," As other situations where we fetch lists this will help us from switching from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/cf-api-v2-usage#Lists"}),"non-local lists")," for more detail on local and non-local lists)."),Object(b.b)("h3",{id:"service_bindingsguid"},Object(b.b)("inlineCode",{parentName:"h3"},"service_bindings/${guid}")),Object(b.b)("p",null,"We don't currently use this, but in order for us to we would need the same as above (list service_bindings)"),Object(b.b)("h3",{id:"service_brokers"},Object(b.b)("inlineCode",{parentName:"h3"},"service_brokers")),Object(b.b)("p",null,"We don't currently use this but it would be very nice to. In order for us to though we would need the following"),Object(b.b)("table",null,Object(b.b)("thead",{parentName:"table"},Object(b.b)("tr",{parentName:"thead"},Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Type"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Name"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Priority"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"UX Example"),Object(b.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(b.b)("tbody",{parentName:"table"},Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"link"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_broker.space")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_broker.space")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"link"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_broker.service_offerings")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"For a given broker show a list of service offerings without making multiple requests"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"include")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"service_broker.service_offerings")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[HIGH]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See above"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"service broker name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"filter"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"space guid"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"See ","[1]")),Object(b.b)("tr",{parentName:"tbody"},Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(b.b)("inlineCode",{parentName:"td"},"order_by")),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"service broker name"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"[MEDIUM]"),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(b.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"see ","[1]")))),Object(b.b)("p",null,"[1]"," As other situations where we fetch lists this will help us from switching from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/cf-api-v2-usage#Lists"}),"non-local lists")," for more detail on local and non-local lists)."),Object(b.b)("h3",{id:"service_brokersguid"},Object(b.b)("inlineCode",{parentName:"h3"},"service_brokers/{guid}")),Object(b.b)("p",null,"We don't currently use this, but in order for us to we would need the same as above (list service_bindings)"),Object(b.b)("h2",{id:"v3-required-features"},"v3 Required Features"),Object(b.b)("h3",{id:"single-included-section-per-request"},"Single 'included` section per request"),Object(b.b)("p",null,"There should hopefully be a single ",Object(b.b)("inlineCode",{parentName:"p"},"included")," section even if ",Object(b.b)("inlineCode",{parentName:"p"},"included")," elements have their own ",Object(b.b)("inlineCode",{parentName:"p"},"include"),"s. Not quite a requirement, but a real nice to have."),Object(b.b)("h3",{id:"included-lists"},Object(b.b)("inlineCode",{parentName:"h3"},"include"),"d lists"),Object(b.b)("p",null,"Ability to set ",Object(b.b)("inlineCode",{parentName:"p"},"include")," for lists of entities. See ",Object(b.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/cc-api-v3-style-guide#proposal-pagination-of-related-resources"}),"https://github.com/cloudfoundry/cc-api-v3-style-guide#proposal-pagination-of-related-resources")),Object(b.b)("p",null,"Use case - Routes, packages, builds, process stats, etc in an application"),Object(b.b)("h3",{id:"order_by-values-in-included-entities"},Object(b.b)("inlineCode",{parentName:"h3"},"order_by")," values in ",Object(b.b)("inlineCode",{parentName:"h3"},"include"),"d entities"),Object(b.b)("p",null,"Ability to use properties of entities that are from the ",Object(b.b)("inlineCode",{parentName:"p"},"included")," section in ",Object(b.b)("inlineCode",{parentName:"p"},"order_by"),"."),Object(b.b)("p",null,"Covers simple case of sorting by a property in a 1:1 ",Object(b.b)("inlineCode",{parentName:"p"},"include")," and also summation of numerical properties in 1:M relationship."),Object(b.b)("p",null,"Use case - sort applications by instance count. Requires ",Object(b.b)("inlineCode",{parentName:"p"},"process")," as an ",Object(b.b)("inlineCode",{parentName:"p"},"include")," and ability to sort applications by sum of ",Object(b.b)("inlineCode",{parentName:"p"},"process"),"s ",Object(b.b)("inlineCode",{parentName:"p"},"instance")," values"),Object(b.b)("p",null,"Use case - as above, but instead of instances the sum of memory in a ",Object(b.b)("inlineCode",{parentName:"p"},"processes")," ",Object(b.b)("inlineCode",{parentName:"p"},"memory_in_mb"),". Need to consider whether ",Object(b.b)("inlineCode",{parentName:"p"},"processes")," state value should be taken into account (only include processes that are running)"),Object(b.b)("p",null,"Use case - as above, but the sum of ",Object(b.b)("inlineCode",{parentName:"p"},"processes")," ",Object(b.b)("inlineCode",{parentName:"p"},"stats")," ",Object(b.b)("inlineCode",{parentName:"p"},"usage.mem"),"."),Object(b.b)("h3",{id:"filter-values-in-included"},"filter values in ",Object(b.b)("inlineCode",{parentName:"h3"},"include"),"d"),Object(b.b)("p",null,"As per ",Object(b.b)("inlineCode",{parentName:"p"},"order_by"),", delve into an ",Object(b.b)("inlineCode",{parentName:"p"},"included")," entity and filter out given a specific path."),Object(b.b)("p",null,"Use case - Filter a list of service bindings by service instance name, service name or service plan name"),Object(b.b)("p",null,"Use case - Filter a list of apps by organization or space"))}o.isMDXComponent=!0},149:function(e,t,a){"use strict";a.d(t,"a",(function(){return p})),a.d(t,"b",(function(){return s}));var n=a(0),l=a.n(n);function b(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function r(e){for(var t=1;t=0||(l[a]=e[a]);return l}(e,t);if(Object.getOwnPropertySymbols){var b=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(l[a]=e[a])}return l}var d=l.a.createContext({}),o=function(e){var t=l.a.useContext(d),a=t;return e&&(a="function"==typeof e?e(t):r(r({},t),e)),a},p=function(e){var t=o(e.components);return l.a.createElement(d.Provider,{value:t},e.children)},O={inlineCode:"code",wrapper:function(e){var t=e.children;return l.a.createElement(l.a.Fragment,{},t)}},j=l.a.forwardRef((function(e,t){var a=e.components,n=e.mdxType,b=e.originalType,i=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),p=o(a),j=n,s=p["".concat(i,".").concat(j)]||p[j]||O[j]||b;return a?l.a.createElement(s,r(r({ref:t},d),{},{components:a})):l.a.createElement(s,r({ref:t},d))}));function s(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var b=a.length,i=new Array(b);i[0]=j;var r={};for(var c in t)hasOwnProperty.call(t,c)&&(r[c]=t[c]);r.originalType=e,r.mdxType="string"==typeof e?e:n,i[1]=r;for(var d=2;d=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=o.a.createContext({}),d=function(e){var t=o.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},u=function(e){var t=d(e.components);return o.a.createElement(l.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},h=o.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,i=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),u=d(n),h=r,b=u["".concat(i,".").concat(h)]||u[h]||p[h]||a;return n?o.a.createElement(b,s(s({ref:t},l),{},{components:n})):o.a.createElement(b,s({ref:t},l))}));function b(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=h;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:r,i[1]=s;for(var l=2;l{const{siteConfig:{themeConfig:{disableDarkMode:e}}={}}=Object(l.a)(),[t,a]=Object(n.useState)("undefined"!=typeof document?document.documentElement.getAttribute("data-theme"):s),r=Object(n.useCallback)(e=>{try{localStorage.setItem("theme",e)}catch(t){console.error(t)}},[a]),c=Object(n.useCallback)(()=>{a(s),r(s)},[]),o=Object(n.useCallback)(()=>{a(i),r(i)},[]);return Object(n.useEffect)(()=>{document.documentElement.setAttribute("data-theme",t)},[t]),Object(n.useEffect)(()=>{if(!e)try{const e=localStorage.getItem("theme");null!==e&&a(e)}catch(t){console.error(t)}},[a]),Object(n.useEffect)(()=>{e||window.matchMedia("(prefers-color-scheme: dark)").addListener(({matches:e})=>{a(e?i:s)})},[]),{isDarkTheme:t===i,setLightTheme:c,setDarkTheme:o}},d=a(159);var m=function(e){const{isDarkTheme:t,setLightTheme:a,setDarkTheme:n}=u();return r.a.createElement(d.a.Provider,{value:{isDarkTheme:t,setLightTheme:a,setDarkTheme:n}},e.children)};var h=()=>{const[e,t]=Object(n.useState)({}),a=Object(n.useCallback)((e,t)=>{try{localStorage.setItem("docusaurus.tab."+e,t)}catch(a){console.error(a)}},[]);return Object(n.useEffect)(()=>{try{const e={};for(let t=0;t{t(t=>({...t,[e]:n})),a(e,n)}}};var f=()=>{const{siteConfig:{themeConfig:{announcementBar:{id:e}={}}}={}}=Object(l.a)(),[t,a]=Object(n.useState)(!0);return Object(n.useEffect)(()=>{if(!e)return;const t=localStorage.getItem("docusaurus.announcement.id"),n=e!==t;localStorage.setItem("docusaurus.announcement.id",e),n&&localStorage.setItem("docusaurus.announcement.dismiss",!1),(n||"false"===localStorage.getItem("docusaurus.announcement.dismiss"))&&a(!1)},[]),{isAnnouncementBarClosed:t,closeAnnouncementBar:()=>{localStorage.setItem("docusaurus.announcement.dismiss",!0),a(!0)}}},b=a(160);var v=function(e){const{tabGroupChoices:t,setTabGroupChoices:a}=h(),{isAnnouncementBarClosed:n,closeAnnouncementBar:c}=f();return r.a.createElement(b.a.Provider,{value:{tabGroupChoices:t,setTabGroupChoices:a,isAnnouncementBarClosed:n,closeAnnouncementBar:c}},e.children)},g=a(161),p=a(92),k=a.n(p);var E=function(){const{siteConfig:{themeConfig:{announcementBar:e={}}}={}}=Object(l.a)(),{content:t,backgroundColor:a,textColor:n}=e,{isAnnouncementBarClosed:c,closeAnnouncementBar:o}=Object(g.a)();return!t||c?null:r.a.createElement("div",{className:k.a.announcementBar,style:{backgroundColor:a,color:n},role:"banner"},r.a.createElement("div",{className:k.a.announcementBarContent,dangerouslySetInnerHTML:{__html:t}}),r.a.createElement("button",{type:"button",className:k.a.announcementBarClose,onClick:o,"aria-label":"Close"},r.a.createElement("span",{"aria-hidden":"true"},"\xd7")))},O=a(2),_=a(151),j=a(152),y=()=>null,C=a(170),w=a.n(C),N=a(93),T=a.n(N);const S=()=>r.a.createElement("span",{className:Object(_.a)(T.a.toggle,T.a.moon)}),B=()=>r.a.createElement("span",{className:Object(_.a)(T.a.toggle,T.a.sun)});var L=function(e){const{isClient:t}=Object(l.a)();return r.a.createElement(w.a,Object(O.a)({disabled:!t,icons:{checked:r.a.createElement(S,null),unchecked:r.a.createElement(B,null)}},e))},x=a(156),M=a(162);var D=function(e){const[t,a]=Object(n.useState)(e);return Object(n.useEffect)(()=>{const e=()=>a(window.location.hash);return window.addEventListener("hashchange",e),()=>window.removeEventListener("hashchange",e)},[]),[t,a]},P=a(163);var I=e=>{const[t,a]=Object(n.useState)(!0),[r,c]=Object(n.useState)(!1),[l,o]=Object(n.useState)(0),[s,i]=Object(n.useState)(0),u=Object(n.useCallback)(e=>{null!==e&&i(e.getBoundingClientRect().height)},[]),d=Object(M.b)(),[m,h]=D(d.hash);return Object(P.a)(({scrollY:t})=>{if(!e)return;if(0===t&&a(!0),t=l?a(!1):t+i{e&&(a(!0),h(d.hash))},[d]),Object(n.useEffect)(()=>{e&&m&&c(!0)},[m]),{navbarRef:u,isNavbarVisible:t}},A=a(164),X=a(165),F=a(166),H=a(94),U=a.n(H);function G({activeBasePath:e,activeBaseRegex:t,to:a,href:n,label:c,activeClassName:l="navbar__link--active",prependBaseUrlToHref:s,...i}){const u=Object(o.a)(a),d=Object(o.a)(e),m=Object(o.a)(n,{forcePrependBaseUrl:!0});return r.a.createElement(j.a,Object(O.a)({},n?{target:"_blank",rel:"noopener noreferrer",href:s?m:n}:{isNavLink:!0,activeClassName:l,to:u,...e||t?{isActive:(e,a)=>t?new RegExp(t).test(a.pathname):a.pathname.startsWith(d)}:null},i),c)}function R({items:e,position:t="right",className:a,...n}){const c=(e,t=!1)=>Object(_.a)({"navbar__item navbar__link":!t,dropdown__link:t},e);return e?r.a.createElement("div",{className:Object(_.a)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--left":"left"===t,"dropdown--right":"right"===t})},r.a.createElement(G,Object(O.a)({className:c(a)},n,{onClick:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&e.target.parentNode.classList.toggle("dropdown--show")}}),n.label),r.a.createElement("ul",{className:"dropdown__menu"},e.map(({className:e,...t},a)=>r.a.createElement("li",{key:a},r.a.createElement(G,Object(O.a)({activeClassName:"dropdown__link--active",className:c(e,!0)},t)))))):r.a.createElement(G,Object(O.a)({className:c(a)},n))}function Y({items:e,position:t,className:a,...n}){const c=(e,t=!1)=>Object(_.a)("menu__link",{"menu__link--sublist":t},e);return e?r.a.createElement("li",{className:"menu__list-item"},r.a.createElement(G,Object(O.a)({className:c(a,!0)},n),n.label),r.a.createElement("ul",{className:"menu__list"},e.map(({className:e,...t},a)=>r.a.createElement("li",{className:"menu__list-item",key:a},r.a.createElement(G,Object(O.a)({activeClassName:"menu__link--active",className:c(e)},t,{onClick:n.onClick})))))):r.a.createElement("li",{className:"menu__list-item"},r.a.createElement(G,Object(O.a)({className:c(a)},n)))}var W=function(){const{siteConfig:{themeConfig:{navbar:{title:e,links:t=[],hideOnScroll:a=!1}={},disableDarkMode:c=!1}},isClient:o}=Object(l.a)(),[s,i]=Object(n.useState)(!1),[u,d]=Object(n.useState)(!1),{isDarkTheme:m,setLightTheme:h,setDarkTheme:f}=Object(x.a)(),{navbarRef:b,isNavbarVisible:v}=I(a),{logoLink:g,logoLinkProps:p,logoImageUrl:k,logoAlt:E}=Object(F.a)();Object(A.a)(s);const C=Object(n.useCallback)(()=>{i(!0)},[i]),w=Object(n.useCallback)(()=>{i(!1)},[i]),N=Object(n.useCallback)(e=>e.target.checked?f():h(),[h,f]),T=Object(X.a)();Object(n.useEffect)(()=>{T===X.b.desktop&&i(!1)},[T]);const{leftLinks:S,rightLinks:B}=function(e){return{leftLinks:e.filter(e=>{var t;return"left"===(null!==(t=e.position)&&void 0!==t?t:"right")}),rightLinks:e.filter(e=>{var t;return"right"===(null!==(t=e.position)&&void 0!==t?t:"right")})}}(t);return r.a.createElement("nav",{ref:b,className:Object(_.a)("navbar","navbar--light","navbar--fixed-top",{"navbar-sidebar--show":s,[U.a.navbarHideable]:a,[U.a.navbarHidden]:!v})},r.a.createElement("div",{className:"navbar__inner"},r.a.createElement("div",{className:"navbar__items"},null!=t&&0!==t.length&&r.a.createElement("div",{"aria-label":"Navigation bar toggle",className:"navbar__toggle",role:"button",tabIndex:0,onClick:C,onKeyDown:C},r.a.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:"30",height:"30",viewBox:"0 0 30 30",role:"img",focusable:"false"},r.a.createElement("title",null,"Menu"),r.a.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))),r.a.createElement(j.a,Object(O.a)({className:"navbar__brand",to:g},p),null!=k&&r.a.createElement("img",{key:o,className:"navbar__logo",src:k,alt:E}),null!=e&&r.a.createElement("strong",{className:Object(_.a)("navbar__title",{[U.a.hideLogoText]:u})},e)),S.map((e,t)=>r.a.createElement(R,Object(O.a)({},e,{key:t})))),r.a.createElement("div",{className:"navbar__items navbar__items--right"},B.map((e,t)=>r.a.createElement(R,Object(O.a)({},e,{key:t}))),!c&&r.a.createElement(L,{className:U.a.displayOnlyInLargeViewport,"aria-label":"Dark mode toggle",checked:m,onChange:N}),r.a.createElement(y,{handleSearchBarToggle:d,isSearchBarExpanded:u}))),r.a.createElement("div",{role:"presentation",className:"navbar-sidebar__backdrop",onClick:w}),r.a.createElement("div",{className:"navbar-sidebar"},r.a.createElement("div",{className:"navbar-sidebar__brand"},r.a.createElement(j.a,Object(O.a)({className:"navbar__brand",onClick:w,to:g},p),null!=k&&r.a.createElement("img",{key:o,className:"navbar__logo",src:k,alt:E}),null!=e&&r.a.createElement("strong",{className:"navbar__title"},e)),!c&&s&&r.a.createElement(L,{"aria-label":"Dark mode toggle in sidebar",checked:m,onChange:N})),r.a.createElement("div",{className:"navbar-sidebar__items"},r.a.createElement("div",{className:"menu"},r.a.createElement("ul",{className:"menu__list"},t.map((e,t)=>r.a.createElement(Y,Object(O.a)({},e,{onClick:w,key:t}))))))))},V=a(95),z=a.n(V);function J({to:e,href:t,label:a,prependBaseUrlToHref:n,...c}){const l=Object(o.a)(e),s=Object(o.a)(t,{forcePrependBaseUrl:!0});return r.a.createElement(j.a,Object(O.a)({className:"footer__link-item"},t?{target:"_blank",rel:"noopener noreferrer",href:n?s:t}:{to:l},c),a)}const K=({url:e,alt:t})=>r.a.createElement("img",{className:"footer__logo",alt:t,src:e});var $=function(){const e=Object(l.a)(),{siteConfig:t={}}=e,{themeConfig:a={}}=t,{footer:n}=a,{copyright:c,links:s=[],logo:i={}}=n||{},u=Object(o.a)(i.src);return n?r.a.createElement("footer",{className:Object(_.a)("footer",{"footer--dark":"dark"===n.style})},r.a.createElement("div",{className:"container"},s&&s.length>0&&r.a.createElement("div",{className:"row footer__links"},s.map((e,t)=>r.a.createElement("div",{key:t,className:"col footer__col"},null!=e.title?r.a.createElement("h4",{className:"footer__title"},e.title):null,null!=e.items&&Array.isArray(e.items)&&e.items.length>0?r.a.createElement("ul",{className:"footer__items"},e.items.map((e,t)=>e.html?r.a.createElement("li",{key:t,className:"footer__item",dangerouslySetInnerHTML:{__html:e.html}}):r.a.createElement("li",{key:e.href||e.to,className:"footer__item"},r.a.createElement(J,e)))):null))),(i||c)&&r.a.createElement("div",{className:"text--center"},i&&i.src&&r.a.createElement("div",{className:"margin-bottom--sm"},i.href?r.a.createElement("a",{href:i.href,target:"_blank",rel:"noopener noreferrer",className:z.a.footerLogoLink},r.a.createElement(K,{alt:i.alt,url:u})):r.a.createElement(K,{alt:i.alt,url:u})),r.a.createElement("div",{dangerouslySetInnerHTML:{__html:c}})))):null};a(96);t.a=function(e){const{siteConfig:t={}}=Object(l.a)(),{favicon:a,title:n,themeConfig:{image:s},url:i}=t,{children:u,title:d,noFooter:h,description:f,image:b,keywords:g,permalink:p,version:k}=e,O=d?`${d} | ${n}`:n,_=b||s,j=Object(o.a)(_,{absolute:!0}),y=Object(o.a)(a);return r.a.createElement(m,null,r.a.createElement(v,null,r.a.createElement(c.a,null,r.a.createElement("html",{lang:"en"}),O&&r.a.createElement("title",null,O),O&&r.a.createElement("meta",{property:"og:title",content:O}),a&&r.a.createElement("link",{rel:"shortcut icon",href:y}),f&&r.a.createElement("meta",{name:"description",content:f}),f&&r.a.createElement("meta",{property:"og:description",content:f}),k&&r.a.createElement("meta",{name:"docsearch:version",content:k}),g&&g.length&&r.a.createElement("meta",{name:"keywords",content:g.join(",")}),_&&r.a.createElement("meta",{property:"og:image",content:j}),_&&r.a.createElement("meta",{property:"twitter:image",content:j}),_&&r.a.createElement("meta",{name:"twitter:image:alt",content:"Image for "+O}),p&&r.a.createElement("meta",{property:"og:url",content:i+p}),p&&r.a.createElement("link",{rel:"canonical",href:i+p}),r.a.createElement("meta",{name:"twitter:card",content:"summary_large_image"})),r.a.createElement(E,null),r.a.createElement(W,null),r.a.createElement("div",{className:"main-wrapper"},u),!h&&r.a.createElement($,null)))}},156:function(e,t,a){"use strict";var n=a(0),r=a(159);t.a=function(){return Object(n.useContext)(r.a)}},159:function(e,t,a){"use strict";var n=a(0);const r=a.n(n).a.createContext({isDarkTheme:!1,setLightTheme:()=>{},setDarkTheme:()=>{}});t.a=r},160:function(e,t,a){"use strict";var n=a(0);const r=Object(n.createContext)({tabGroupChoices:{},setTabGroupChoices:()=>{},isAnnouncementBarClosed:!1,closeAnnouncementBar:()=>{}});t.a=r},161:function(e,t,a){"use strict";var n=a(0),r=a(160);t.a=function(){return Object(n.useContext)(r.a)}},162:function(e,t,a){"use strict";var n=a(19);a.d(t,"a",(function(){return n.d})),a.d(t,"b",(function(){return n.e}))},163:function(e,t,a){"use strict";var n=a(0),r=a(15);const c=()=>({scrollX:r.a.canUseDOM?window.pageXOffset:0,scrollY:r.a.canUseDOM?window.pageYOffset:0});t.a=(e,t=[])=>{const[a,r]=Object(n.useState)(c()),l=()=>{const t=c();r(t),e&&e(t)};return Object(n.useEffect)(()=>(window.addEventListener("scroll",l),()=>window.removeEventListener("scroll",l,{passive:!0})),t),a}},164:function(e,t,a){"use strict";var n=a(0);t.a=function(e=!0){Object(n.useEffect)(()=>(document.body.style.overflow=e?"hidden":"visible",()=>{document.body.style.overflow="visible"}),[e])}},165:function(e,t,a){"use strict";a.d(t,"b",(function(){return r}));var n=a(0);const r={desktop:"desktop",mobile:"mobile"};t.a=function(){const e="undefined"!=typeof window;function t(){if(e)return window.innerWidth>996?r.desktop:r.mobile}const[a,c]=Object(n.useState)(t);return Object(n.useEffect)(()=>{if(!e)return!1;function a(){c(t())}return window.addEventListener("resize",a),()=>window.removeEventListener("resize",a)},[]),a}},166:function(e,t,a){"use strict";var n=a(150),r=a(156),c=a(153),l=a(154);t.a=()=>{const{siteConfig:{themeConfig:{navbar:{logo:e={}}={}}}={}}=Object(n.a)(),{isDarkTheme:t}=Object(r.a)(),a=Object(c.a)(e.href||"/");let o={};e.target?o={target:e.target}:Object(l.a)(a)||(o={rel:"noopener noreferrer",target:"_blank"});const s=e.srcDark&&t?e.srcDark:e.src;return{logoLink:a,logoLinkProps:o,logoImageUrl:Object(c.a)(s),logoAlt:e.alt}}},170:function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=Object.assign||function(e){for(var t=1;tthis.startX&&(this.setState({checked:!0}),this.startX=t,this.activated=ta?this.previouslyChecked!==this.state.checked&&(this.setState({checked:!1}),this.previouslyChecked=this.state.checked,t.click()):this.startX-4=0||Object.prototype.hasOwnProperty.call(e,n)&&(a[n]=e[n]);return a}(t,["className","icons"])),c=(0,o.default)("react-toggle",{"react-toggle--checked":this.state.checked,"react-toggle--focus":this.state.hasFocus,"react-toggle--disabled":this.props.disabled},a);return l.default.createElement("div",{className:c,onClick:this.handleClick,onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouchMove,onTouchEnd:this.handleTouchEnd},l.default.createElement("div",{className:"react-toggle-track"},l.default.createElement("div",{className:"react-toggle-track-check"},this.getIcon("checked")),l.default.createElement("div",{className:"react-toggle-track-x"},this.getIcon("unchecked"))),l.default.createElement("div",{className:"react-toggle-thumb"}),l.default.createElement("input",n({},r,{ref:function(t){e.input=t},onFocus:this.handleFocus,onBlur:this.handleBlur,className:"react-toggle-screenreader-only",type:"checkbox"})))}}]),t}(c.PureComponent);t.default=h,h.displayName="Toggle",h.defaultProps={icons:{checked:l.default.createElement(i.default,null),unchecked:l.default.createElement(u.default,null)}},h.propTypes={checked:s.default.bool,disabled:s.default.bool,defaultChecked:s.default.bool,onChange:s.default.func,onFocus:s.default.func,onBlur:s.default.func,className:s.default.string,name:s.default.string,value:s.default.string,id:s.default.string,"aria-labelledby":s.default.string,"aria-label":s.default.string,icons:s.default.oneOfType([s.default.bool,s.default.shape({checked:s.default.node,unchecked:s.default.node})])}},171:function(e,t,a){var n;!function(){"use strict";var a={}.hasOwnProperty;function r(){for(var e=[],t=0;t0){var a=t[0];return{x:a.clientX,y:a.clientY}}var n=e.pageX;if(void 0!==n)return{x:n,y:e.pageY}}return{x:0,y:0}}}}]); \ No newline at end of file diff --git a/website/site-dist/2.b943da11.js.LICENSE.txt b/website/site-dist/2.b943da11.js.LICENSE.txt new file mode 100644 index 0000000000..bae6dd8e22 --- /dev/null +++ b/website/site-dist/2.b943da11.js.LICENSE.txt @@ -0,0 +1,5 @@ +/*! + Copyright (c) 2017 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/ diff --git a/website/site-dist/20ac7829.e87d6cb5.js b/website/site-dist/20ac7829.e87d6cb5.js new file mode 100644 index 0000000000..330b8c5478 --- /dev/null +++ b/website/site-dist/20ac7829.e87d6cb5.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{111:function(e){e.exports=JSON.parse('{"docsSidebars":{"docs":[{"collapsed":true,"type":"category","label":"Documentation","items":[{"type":"link","label":"Introduction","href":"/docs/"},{"type":"link","label":"Overview","href":"/docs/overview"}]},{"collapsed":true,"type":"category","label":"Deploying Stratos","items":[{"type":"link","label":"Overview","href":"/docs/deploy/deploy-overview"},{"collapsed":true,"type":"category","label":"Cloud Foundry","items":[{"type":"link","label":"Deploy on Cloud Foundry","href":"/docs/deploy/cloud-foundry/cloud-foundry"},{"type":"link","label":"Database service bindings","href":"/docs/deploy/cloud-foundry/db-migration"},{"type":"link","label":"Troubleshooting","href":"/docs/deploy/cloud-foundry/cf-troubleshooting"}]},{"collapsed":true,"type":"category","label":"Kubernetes","items":[{"type":"link","label":"Overview","href":"/docs/deploy/kubernetes"},{"type":"link","label":"Deploy using Helm","href":"/docs/deploy/kubernetes/helm-installation"}]},{"type":"link","label":"Docker All-in-One","href":"/docs/deploy/all-in-one"},{"type":"link","label":"Accessing Stratos","href":"/docs/deploy/access"},{"type":"link","label":"Troubleshooting","href":"/docs/deploy/troubleshooting"}]},{"collapsed":true,"type":"category","label":"Advanced Topics","items":[{"type":"link","label":"Configuring User Invites","href":"/docs/advanced/invite-user-guide"},{"type":"link","label":"Configuring Single Sign On","href":"/docs/advanced/sso"}]},{"collapsed":true,"type":"category","label":"Contributing to Development","items":[{"type":"link","label":"Contributing to Stratos","href":"/docs/guides/contribution/contributing"},{"type":"link","label":"Stratos Development","href":"/docs/developer/introduction"},{"collapsed":true,"type":"category","label":"Frontend","items":[{"type":"link","label":"Overview","href":"/docs/developer/frontend"},{"type":"link","label":"Tests","href":"/docs/developer/frontend-tests"}]},{"collapsed":true,"type":"category","label":"Backend","items":[{"type":"link","label":"Overview","href":"/docs/developer/backend"}]},{"type":"link","label":"Dev Environment","href":"/docs/developer/developers-guide-env-tech"},{"type":"link","label":"E2E Tests","href":"/docs/developer/developers-guide-e2e-tests"}]},{"collapsed":true,"type":"category","label":"Extending Stratos","items":[{"type":"link","label":"Introduction","href":"/docs/extensions/introduction"},{"type":"link","label":"Customizing Stratos","href":"/docs/guides/customization/customizing"},{"type":"link","label":"Theming Stratos","href":"/docs/extensions/theming"},{"type":"link","label":"Frontend Extensions","href":"/docs/extensions/frontend"},{"type":"link","label":"Backend Plugins","href":"/docs/extensions/backend"}]}]},"permalinkToSidebar":{"/docs/":"docs","/docs/advanced/invite-user-guide":"docs","/docs/advanced/sso":"docs","/docs/deploy/access":"docs","/docs/deploy/all-in-one":"docs","/docs/deploy/cloud-foundry/cf-troubleshooting":"docs","/docs/deploy/cloud-foundry/cloud-foundry":"docs","/docs/deploy/cloud-foundry/db-migration":"docs","/docs/deploy/deploy-overview":"docs","/docs/deploy/kubernetes":"docs","/docs/deploy/kubernetes/helm-installation":"docs","/docs/deploy/troubleshooting":"docs","/docs/developer/backend":"docs","/docs/developer/developers-guide-e2e-tests":"docs","/docs/developer/developers-guide-env-tech":"docs","/docs/developer/frontend":"docs","/docs/developer/frontend-tests":"docs","/docs/developer/introduction":"docs","/docs/extensions/backend":"docs","/docs/extensions/frontend":"docs","/docs/extensions/introduction":"docs","/docs/extensions/theming":"docs","/docs/guides/contribution/contributing":"docs","/docs/guides/customization/customizing":"docs","/docs/overview":"docs"}}')}}]); \ No newline at end of file diff --git a/website/site-dist/23b39e02.8cebdea5.js b/website/site-dist/23b39e02.8cebdea5.js new file mode 100644 index 0000000000..528e716ee0 --- /dev/null +++ b/website/site-dist/23b39e02.8cebdea5.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{112:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return o})),n.d(t,"metadata",(function(){return l})),n.d(t,"rightToc",(function(){return c})),n.d(t,"default",(function(){return u}));var a=n(2),i=n(6),r=(n(0),n(149)),o={title:"Backend Development",sidebar_label:"Overview"},l={id:"developer/backend",isDocsHomePage:!1,title:"Backend Development",description:"Backend Development",source:"@site/docs/developer/backend.md",permalink:"/docs/developer/backend",editUrl:"https://github.com/cloudfoundry/stratos/edit/master/website/docs/developer/backend.md",sidebar_label:"Overview",sidebar:"docs",previous:{title:"Frontend Tests",permalink:"/docs/developer/frontend-tests"},next:{title:"Stratos Tech + Developer Environment",permalink:"/docs/developer/developers-guide-env-tech"}},c=[{value:"Backend Development",id:"backend-development",children:[{value:"Pre-requisites",id:"pre-requisites",children:[]},{value:"Building the back-end",id:"building-the-back-end",children:[]},{value:"Configuration",id:"configuration",children:[]}]}],b={rightToc:c};function u(e){var t=e.components,n=Object(i.a)(e,["components"]);return Object(r.b)("wrapper",Object(a.a)({},b,n,{components:t,mdxType:"MDXLayout"}),Object(r.b)("h2",{id:"backend-development"},"Backend Development"),Object(r.b)("p",null,"Jetstream is the back-end for Stratos. It is written in Go."),Object(r.b)("p",null,"We use Go Modules for dependency management."),Object(r.b)("h3",{id:"pre-requisites"},"Pre-requisites"),Object(r.b)("p",null,"You will need the following installed/available:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"go 1.12 or later.")),Object(r.b)("p",null,"*For authentication, ",Object(r.b)("strong",{parentName:"p"},"either*")),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"A UAA instance"),Object(r.b)("li",{parentName:"ul"},"A local user account ")),Object(r.b)("h3",{id:"building-the-back-end"},"Building the back-end"),Object(r.b)("h4",{id:"build"},"Build"),Object(r.b)("p",null,"From the ",Object(r.b)("inlineCode",{parentName:"p"},"src/jetstream")," folder, build the Stratos back-end with:"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{}),"npm run build-backend\n")),Object(r.b)("p",null,"The back-end executable is named ",Object(r.b)("inlineCode",{parentName:"p"},"jetstream")," and should be created within the ",Object(r.b)("inlineCode",{parentName:"p"},"src/jetstream")," folder."),Object(r.b)("h3",{id:"configuration"},"Configuration"),Object(r.b)("p",null,"Configuration can either be done via"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Environment Variable and/or Config File"),Object(r.b)("li",{parentName:"ul"},"In the UI when you first use a front end with this backend")),Object(r.b)("p",null,"In all cases the configuration is saved to the database on first run. Any subsequent changes require the db to be reset. For the default sqlite\ndb provider this can be done by deleting ",Object(r.b)("inlineCode",{parentName:"p"},"src/jetstream/console-database.db")),Object(r.b)("h4",{id:"configure-by-environment-variables-andor-config-file"},"Configure by Environment Variables and/or Config File"),Object(r.b)("p",null,"By default, the configuration in file ",Object(r.b)("inlineCode",{parentName:"p"},"src/jetstream/default.config.properties")," will be used. These can be changed by environment variables\nor an overrides file."),Object(r.b)("h5",{id:"environment-variable"},"Environment variable"),Object(r.b)("p",null,"If you wish to use a local user account, ensure you have set the following environment variables:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"AUTH_ENDPOINT_TYPE=local")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"LOCAL_USER")," - The username for the local user"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"LOCAL_USER_PASSWORD")," - The password for the local user"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"LOCAL_USER_SCOPE=stratos.admin")," - This gives the local user admin permissions. Currently other roles are not available.")),Object(r.b)("p",null,"If you have a custom uaa, ensure you have set the following environment variables:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"UAA_ENDPOINT"),"- the URL of your UAA",Object(r.b)("ul",{parentName:"li"},Object(r.b)("li",{parentName:"ul"},"If you have an existing CF and want to use the same UAA use the ",Object(r.b)("inlineCode",{parentName:"li"},"authorization_endpoint")," value from ",Object(r.b)("inlineCode",{parentName:"li"},"[cf url]/v2/info"),"\nFor example for PCF Dev, use: ",Object(r.b)("inlineCode",{parentName:"li"},"UAA_ENDPOINT=https://login.local.pcfdev.io"),"."))),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"CONSOLE_CLIENT")," - the Client ID to use when authenticating against your UAA (defaults to: 'cf')"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"CONSOLE_CLIENT_SECRET")," - the Client ID to use when authenticating against your UAA (defaults to empty)"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"CONSOLE_ADMIN_SCOPE")," - an existing UAA scope that will be used to identify users as ",Object(r.b)("inlineCode",{parentName:"li"},"Stratos Admins"))),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"To use a pre-built Stratos UAA container execute ",Object(r.b)("inlineCode",{parentName:"p"},"docker run --name=uaa --rm -p 8080:8080 -P splatform/stratos-uaa"),". The UAA will be\navailable at ",Object(r.b)("inlineCode",{parentName:"p"},"http://localhost:8080")," with a ",Object(r.b)("inlineCode",{parentName:"p"},"CONSOLE_CLIENT")," value of ",Object(r.b)("inlineCode",{parentName:"p"},"console"))),Object(r.b)("h5",{id:"config-file"},"Config File"),Object(r.b)("p",null,"To easily persist configuration settings copy ",Object(r.b)("inlineCode",{parentName:"p"},"src/jetstream/default.config.properties")," to ",Object(r.b)("inlineCode",{parentName:"p"},"src/jetstream/config.properties"),". The backend will load its\nconfiguration from this file in preference to the default config file, if it exists. You can also modify individual configuration settings\nby setting the corresponding environment variable."),Object(r.b)("h5",{id:"to-configure-a-local-user-account-via-config-file"},"To configure a local user account via config file"),Object(r.b)("p",null,"In ",Object(r.b)("inlineCode",{parentName:"p"},"src/jetstream/config.properties")," uncomment the following lines:"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{}),"AUTH_ENDPOINT_TYPE=local\nLOCAL_USER=localuser\nLOCAL_USER_PASSWORD=localuserpass\nLOCAL_USER_SCOPE=stratos.admin\n")),Object(r.b)("p",null,"Load the Stratos UI and proceed to log in using the configured credentials."),Object(r.b)("h4",{id:"to-configure-uaa-via-stratos"},"To configure UAA via Stratos"),Object(r.b)("ol",null,Object(r.b)("li",{parentName:"ol"},"Go through the ",Object(r.b)("inlineCode",{parentName:"li"},"Config File")," step above and comment out the ",Object(r.b)("inlineCode",{parentName:"li"},"UAA_ENDPOINT")," with a ",Object(r.b)("inlineCode",{parentName:"li"},"#")," in the new ",Object(r.b)("inlineCode",{parentName:"li"},"config.properties")," file."),Object(r.b)("li",{parentName:"ol"},"If any previous configuration attempt has been made reset your database as described above."),Object(r.b)("li",{parentName:"ol"},"Continue these steps from ",Object(r.b)("a",Object(a.a)({parentName:"li"},{href:"#run"}),"Run"),".",Object(r.b)("ul",{parentName:"li"},Object(r.b)("li",{parentName:"ul"},"You should see the line ",Object(r.b)("inlineCode",{parentName:"li"},"Will add setup route and middleware")," in the logs"))),Object(r.b)("li",{parentName:"ol"},"Load the Stratos UI as usual and you should be immediately directed to the setup wizard")),Object(r.b)("p",null,"The setup wizard that allows you to enter the values normally fetched from environment variables or files. The UI will assist you through\nthis process, validating that the UAA address and credentials are correct. It will also provide a list of possible scopes for the Stratos Admin"),Object(r.b)("h4",{id:"run"},"Run"),Object(r.b)("p",null,"Execute the following file from ",Object(r.b)("inlineCode",{parentName:"p"},"src/jetstream")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{}),"jetstream\n")),Object(r.b)("p",null,"You should see the log as the backend starts up. You can press CTRL+C to stop the backend."),Object(r.b)("h4",{id:"automatically-register-and-connect-to-an-existing-endpoint"},"Automatically register and connect to an existing endpoint"),Object(r.b)("p",null,"To automatically register a Cloud Foundry add the environment variable/config setting below:"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{}),"AUTO_REG_CF_URL=\n")),Object(r.b)("p",null,"Jetstream will then attempt to auto-connect to it with the credentials supplied when logging into Stratos."),Object(r.b)("h4",{id:"running-jetstream-in-a-container"},"Running Jetstream in a container"),Object(r.b)("p",null,"We recommend running Stratos using the Docker All-In-One image."),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Follow instructions in the deploy/all-in-one docs")))}u.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return s})),n.d(t,"b",(function(){return m}));var a=n(0),i=n.n(a);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var b=i.a.createContext({}),u=function(e){var t=i.a.useContext(b),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},s=function(e){var t=u(e.components);return i.a.createElement(b.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return i.a.createElement(i.a.Fragment,{},t)}},p=i.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,o=e.parentName,b=c(e,["components","mdxType","originalType","parentName"]),s=u(n),p=a,m=s["".concat(o,".").concat(p)]||s[p]||d[p]||r;return n?i.a.createElement(m,l(l({ref:t},b),{},{components:n})):i.a.createElement(m,l({ref:t},b))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,o=new Array(r);o[0]=p;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var b=2;b 3306/TCP 60s\nmy-console-ui-ext NodePort 10.109.207.70 443:31067/TCP 60s\n")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"In this example, Stratos has been deployed withe the service configured as ",Object(r.b)("inlineCode",{parentName:"p"},"NodePort"),".")),Object(r.b)("p",null,"The URL you use for accessing Stratos will depend on the service configuration and the environment that you have used."),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: If you did not provide a certificate when installing, Stratos will use a self-signed certificate, so you will see a certificate warning which you access Stratos in a browser.")),Object(r.b)("h1",{id:"upgrading-your-deployment"},"Upgrading your deployment"),Object(r.b)("p",null,"To upgrade your instance when using the Helm repository, fetch any updates to the repository:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"helm repo update\n")),Object(r.b)("p",null,"To update an instance, the following assumes your instance is called ",Object(r.b)("inlineCode",{parentName:"p"},"my-console"),":"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"helm upgrade my-console stratos/console\n")),Object(r.b)("p",null,"After the upgrade, perform a ",Object(r.b)("inlineCode",{parentName:"p"},"helm list")," to ensure your console is the latest version."),Object(r.b)("h2",{id:"uninstalling"},"Uninstalling"),Object(r.b)("p",null,"To uninstall Stratos, delete the Helm release and also delete the Kubernetes namespace:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"helm delete my-console --purge\nkubectl delete namespace console\n")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: Stratos creates secrets in the namespace as part of an initialization job. These are not managed by Helm, so make sure you\ndelete the namespace to remove these secrets. ")),Object(r.b)("h1",{id:"advanced-topics"},"Advanced Topics"),Object(r.b)("h2",{id:"using-a-load-balancer"},"Using a Load Balancer"),Object(r.b)("p",null,"If your Kubernetes deployment supports automatic configuration of a load balancer (e.g. Google Container Engine), specify the parameters ",Object(r.b)("inlineCode",{parentName:"p"},"console.service.type=LoadBalancer")," when installing."),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"kubectl create namespace console\nhelm install my-console stratos/console --namespace=console --set console.service.type=LoadBalancer\n")),Object(r.b)("h2",{id:"using-an-ingress-controller"},"Using an Ingress Controller"),Object(r.b)("p",null,"If your Kubernetes Cluster supports Ingress, you can expose Stratos through Ingress by supplying the appropriate ingress configuration when installing."),Object(r.b)("p",null,"This configuration is described below:"),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Parameter"),Object(r.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Description"),Object(r.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Default"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.service.ingress.enabled"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Enables ingress"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"false")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.service.ingress.annotations"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Annotations to be added to the ingress resource."),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"{}")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.service.ingress.extraLabels"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Additional labels to be added to the ingress resource."),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"{}")),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.service.ingress.host"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"The host name that will be used for the Stratos service."),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.service.ingress.secretName"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"The existing TLS secret that contains the certificate for ingress."),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))))),Object(r.b)("p",null,"You must provide ",Object(r.b)("inlineCode",{parentName:"p"},"console.service.ingress.host")," when enabling ingress."),Object(r.b)("p",null,"By default a certificate will be generated for TLS. You can provide your own certificate by creating a secret and specifying this with ",Object(r.b)("inlineCode",{parentName:"p"},"console.service.ingress.secretName"),"."),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: If you do not supply ",Object(r.b)("inlineCode",{parentName:"p"},"console.service.ingress.host")," but do supply ",Object(r.b)("inlineCode",{parentName:"p"},"env.DOMAIN")," then the host ",Object(r.b)("inlineCode",{parentName:"p"},"console.[env.DOMAIN]")," will be used.")),Object(r.b)("h2",{id:"deploying-from-a-private-image-repository"},"Deploying from a Private Image Repository"),Object(r.b)("p",null,"If the images used by the chart are hosted in a private repository, the following needs to be specified. Save the following to a file called ",Object(r.b)("inlineCode",{parentName:"p"},"private_overrides.yaml"),". Replace ",Object(r.b)("inlineCode",{parentName:"p"},"REGISTRY USER PASSSWORD"),", ",Object(r.b)("inlineCode",{parentName:"p"},"REGISTRY USERNAME"),", ",Object(r.b)("inlineCode",{parentName:"p"},"REGISTRY URL")," with the appropriate values. ",Object(r.b)("inlineCode",{parentName:"p"},"USER EMAIL")," can be left blank."),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"kube:\n registry:\n password: \n username: \n hostname: \n email: \n")),Object(r.b)("p",null,"Deploy with:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"kubectl create namespace console\nhelm install my-console stratos/console --namespace=console -f private_overrides.yaml\n")),Object(r.b)("h2",{id:"deploying-with-your-own-tls-certificates"},"Deploying with your own TLS certificates"),Object(r.b)("p",null,"By default the console will generate self-signed certificates for demo purposes. To configure Stratos to use your provided TLS certificate, create a TLS secret in the namespace you are installing into and specify this secret name using the helm chart value ",Object(r.b)("inlineCode",{parentName:"p"},"console.tlsSecretName")," when installing."),Object(r.b)("p",null,"Assuming you have your certificate and key in the files ",Object(r.b)("inlineCode",{parentName:"p"},"tls.crt")," and ",Object(r.b)("inlineCode",{parentName:"p"},"tls.key"),", create the secret with:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"kubectl create secret tls -n NAMESPACE stratos-tls-secret --cert=tls.crt --key=tls.key\n")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Where ",Object(r.b)("inlineCode",{parentName:"p"},"NAMESPACE")," is the namespace you are installing Stratos into - you will need to manually create the namespace first if it does not already exist.")),Object(r.b)("p",null,"You can now install Stratos with:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"kubectl create namespace console\nhelm install my-console stratos/console --namespace=console --set console.tlsSecretName=stratos-tls-secret\n\n")),Object(r.b)("h2",{id:"using-an-external-database"},"Using an External Database"),Object(r.b)("p",null,"You can choose to use Stratos with an external database, rather than deploying a single-node MariaDB instance as part of the Helm install."),Object(r.b)("p",null,"To do so, specify ",Object(r.b)("inlineCode",{parentName:"p"},"console.mariabdb.external=true")," when deploying."),Object(r.b)("p",null,"You will also need to specify:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"console.mariadb.host")," as the hostname of the external MariaDB database server"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"console.mariadb.port")," as the port of the external MariaDB database server (defaults to 3306)"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"console.mariadb.tls")," as the TLS mode (default is ",Object(r.b)("inlineCode",{parentName:"li"},"false,")," use ",Object(r.b)("inlineCode",{parentName:"li"},"true")," for a TLS connection to the database server)"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"console.mariadb.database")," as the name of the database"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"console.mariadb.user")," as the username to connect to the database server"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"console.mariadb.userPassword")," as the password to connect to the database server")),Object(r.b)("p",null,"When using an external database server, Stratos expects that you have:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Created a user that will be used to access the database"),Object(r.b)("li",{parentName:"ul"},"Created a database for the Stratos tables and data"),Object(r.b)("li",{parentName:"ul"},"Granted appropriate permissions so that the user can access the database")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: When using a database from a Cloud provider, ensure that the username is correct - in some cases this will be ",Object(r.b)("inlineCode",{parentName:"p"},"username@servername")," - check the provided connection documentation")),Object(r.b)("h2",{id:"specifying-uaa-configuration"},"Specifying UAA configuration"),Object(r.b)("p",null,"When deploying with SCF, the ",Object(r.b)("inlineCode",{parentName:"p"},"scf-config-values.yaml")," (see ",Object(r.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/SUSE/scf/wiki/How-to-Install-SCF#configuring-the-deployment"}),"SCF Wiki link"),") can be supplied when installing Stratos."),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"kubectl create namespace console\nhelm install my-console stratos/console --namespace=console -f scf-config-values.yaml\n")),Object(r.b)("p",null,"UAA configuration can be specified by providing the following configuration."),Object(r.b)("p",null,"Create a yaml file with the content below and and update according to your environment and save to a file called ",Object(r.b)("inlineCode",{parentName:"p"},"uaa-config.yaml"),"."),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"uaa:\n endpoint: https://uaa.cf-dev.io:2793\n consoleClient: cf\n consoleClientSecret: \n consoleAdminIdentifier: cloud_controller.admin \n skipSSLValidation: false\n")),Object(r.b)("p",null,"To install Stratos with the above specified configuration:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"kubectl create namespace console\nhelm install my-console stratos/console --namespace=console -f uaa-config.yaml\n")),Object(r.b)("h2",{id:"configuring-a-local-user-account"},"Configuring a local user account"),Object(r.b)("p",null,"This allows for deployment without a UAA. To enable the local user account, supply a password for the local user in the deployment command, as follows. All other steps for each deployment method should be followed as in the preceding sections above."),Object(r.b)("p",null,"To deploy using our Helm repository:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"kubectl create namespace console\nhelm install my-console stratos/console --namespace=console --set console.localAdminPassword=\n")),Object(r.b)("h2",{id:"specifying-annotations-and-labels"},"Specifying Annotations and Labels"),Object(r.b)("p",null,"In some scenarios it is useful to be able to add custom annotations and/or labels to the Kubernetes resources that the Stratos Helm chart creates."),Object(r.b)("p",null,"The Stratos Helm chart exposes a number of Helm chart values that cabe specified in order to do this - they are:"),Object(r.b)("table",null,Object(r.b)("thead",{parentName:"table"},Object(r.b)("tr",{parentName:"thead"},Object(r.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Parameter"),Object(r.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Description"),Object(r.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Default"))),Object(r.b)("tbody",{parentName:"table"},Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.podAnnotations"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Annotations to be added to all pod resources"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.podExtraLabels"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Additional labels to be added to all pod resources"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.statefulSetAnnotations"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Annotations to be added to all statefulset resources"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.statefulSetExtraLabels"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Additional labels to be added to all statefulset resources"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.deploymentAnnotations"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Annotations to be added to all deployment resources"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.deploymentExtraLabels"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Additional labels to be added to all deployment resources"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.jobAnnotations"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Annotations to be added to all job resources"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.jobExtraLabels"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Additional labels to be added to all job resources"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.service.annotations"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Annotations to be added to all service resources"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.service.extraLabels"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Additional labels to be added to all service resources"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.service.ingress.annotations"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Annotations to be added to the ingress resource"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(r.b)("tr",{parentName:"tbody"},Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"console.service.ingress.extraLabels"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Additional labels to be added to the ingress resource"),Object(r.b)("td",Object(n.a)({parentName:"tr"},{align:null}))))),Object(r.b)("h2",{id:"requirements"},"Requirements"),Object(r.b)("h3",{id:"storage-class"},"Storage Class"),Object(r.b)("p",null,"Stratos uses persistent volumes. In order to deploy it in your Kubernetes environment, you must\nhave a storage class available."),Object(r.b)("p",null,"Without configuration, the Stratos Helm Chart will use the default storage class. If a default storage\nclass is not available, installation will fail."),Object(r.b)("p",null,"To check if a ",Object(r.b)("inlineCode",{parentName:"p"},"default")," storage class exists, you can list your configured storage classes with ",Object(r.b)("inlineCode",{parentName:"p"},"kubectl get storageclass"),". If no storage class has ",Object(r.b)("inlineCode",{parentName:"p"},"(default)")," after it, then you need to either specify a storage class override or declare a default storage class for your Kubernetes cluster."),Object(r.b)("p",null,"For non-production environments, you may want to use the ",Object(r.b)("inlineCode",{parentName:"p"},"hostpath")," storage class. See the ",Object(r.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/SUSE/scf/wiki/How-to-Install-SCF#choosing-a-storage-class"}),"SCF instructions")," for details on setting this up. Note that you will need to make this storage class the default storage class, e.g."),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),'kubectl patch storageclass -p \'{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}\'\n')),Object(r.b)("p",null,"Where ",Object(r.b)("inlineCode",{parentName:"p"},"")," would be ",Object(r.b)("inlineCode",{parentName:"p"},"hostpath")," if you follow the SCF instructions."),Object(r.b)("h3",{id:"specifying-a-custom-storage-class"},"Specifying a custom Storage Class"),Object(r.b)("p",null,"If no default storage class has been defined in the Kubernetes cluster. The Stratos helm chart will fail to deploy successfully. To check if a ",Object(r.b)("inlineCode",{parentName:"p"},"default")," storage class exists, you can list your configured storage classes with ",Object(r.b)("inlineCode",{parentName:"p"},"kubectl"),". If no storage class has ",Object(r.b)("inlineCode",{parentName:"p"},"(default)")," after it, then you need to either specify a storage class override or declare a default storage class for your Kubernetes cluster."),Object(r.b)("h4",{id:"providing-storage-class-override"},"Providing Storage Class override"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"kubectl get storageclass\nNAME TYPE\nssd kubernetes.io/host-path \npersistent kubernetes.io/host-path \n")),Object(r.b)("p",null,"For instance to use the storage class ",Object(r.b)("inlineCode",{parentName:"p"},"persistent")," to deploy Console persistent volume claims, store the following to a file called ",Object(r.b)("inlineCode",{parentName:"p"},"override.yaml"),"."),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"---\nstorageClass: persistent\n")),Object(r.b)("p",null,"If you want MariaDB to use a specific storage class (which can be different to that used for the other components), then specify the following:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"---\nstorageClass: persistent\nmariadb:\n persistence:\n storageClass: persistent\n")),Object(r.b)("p",null,"Run Helm with the override:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"kubectl create namespace console\nhelm install my-console stratos/console --namespace=console -f override.yaml\n")),Object(r.b)("h4",{id:"create-a-default-storage-class"},"Create a default Storage Class"),Object(r.b)("p",null,"Alternatively, you can configure a storage class with ",Object(r.b)("inlineCode",{parentName:"p"},"storageclass.kubernetes.io/is-default-class")," set to ",Object(r.b)("inlineCode",{parentName:"p"},"true"),". For instance the following storage class will be declared as the default. If you don't have the ",Object(r.b)("inlineCode",{parentName:"p"},"hostpath")," provisioner available in your local cluster, please follow the instructions on ",Object(r.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/kubernetes-incubator/external-storage/tree/master/docs/demo/hostpath-provisioner"}),"link"),", to deploy one."),Object(r.b)("p",null,"If the hostpath provisioner is available, save the file to ",Object(r.b)("inlineCode",{parentName:"p"},"storageclass.yaml")),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),'---\nkind: StorageClass\napiVersion: storage.k8s.io/v1beta1\nmetadata:\n name: default\n annotations:\n storageclass.kubernetes.io/is-default-class: "true"\nprovisioner: kubernetes.io/host-path # Or whatever the local hostpath provisioner is called\n')),Object(r.b)("p",null,"To create it in your kubernetes cluster, execute the following."),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{}),"kubectl create -f storageclass.yaml\n")),Object(r.b)("p",null,"See ",Object(r.b)("a",Object(n.a)({parentName:"p"},{href:"https://kubernetes.io/docs/tasks/administer-cluster/change-default-storage-class/"}),"Storage Class documentation")," for more information."))}i.isMDXComponent=!0},149:function(e,t,a){"use strict";a.d(t,"a",(function(){return d})),a.d(t,"b",(function(){return O}));var n=a(0),l=a.n(n);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function b(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function o(e){for(var t=1;t=0||(l[a]=e[a]);return l}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(l[a]=e[a])}return l}var s=l.a.createContext({}),i=function(e){var t=l.a.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},d=function(e){var t=i(e.components);return l.a.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return l.a.createElement(l.a.Fragment,{},t)}},u=l.a.forwardRef((function(e,t){var a=e.components,n=e.mdxType,r=e.originalType,b=e.parentName,s=c(e,["components","mdxType","originalType","parentName"]),d=i(a),u=n,O=d["".concat(b,".").concat(u)]||d[u]||p[u]||r;return a?l.a.createElement(O,o(o({ref:t},s),{},{components:a})):l.a.createElement(O,o({ref:t},s))}));function O(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var r=a.length,b=new Array(r);b[0]=u;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:n,b[1]=o;for(var s=2;s=0||(l[a]=e[a]);return l}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(l[a]=e[a])}return l}var c=l.a.createContext({}),u=function(e){var t=l.a.useContext(c),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},p=function(e){var t=u(e.components);return l.a.createElement(c.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return l.a.createElement(l.a.Fragment,{},t)}},m=l.a.forwardRef((function(e,t){var a=e.components,r=e.mdxType,n=e.originalType,i=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),p=u(a),m=r,d=p["".concat(i,".").concat(m)]||p[m]||b[m]||n;return a?l.a.createElement(d,s(s({ref:t},c),{},{components:a})):l.a.createElement(d,s({ref:t},c))}));function d(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var n=a.length,i=new Array(n);i[0]=m;var s={};for(var o in t)hasOwnProperty.call(t,o)&&(s[o]=t[o]);s.originalType=e,s.mdxType="string"==typeof e?e:r,i[1]=s;for(var c=2;c=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var b=a.a.createContext({}),u=function(e){var t=a.a.useContext(b),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},s=function(e){var t=u(e.components);return a.a.createElement(b.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},d=a.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,l=e.parentName,b=o(e,["components","mdxType","originalType","parentName"]),s=u(n),d=r,m=s["".concat(l,".").concat(d)]||s[d]||p[d]||i;return n?a.a.createElement(m,c(c({ref:t},b),{},{components:n})):a.a.createElement(m,c({ref:t},b))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,l=new Array(i);l[0]=d;var c={};for(var o in t)hasOwnProperty.call(t,o)&&(c[o]=t[o]);c.originalType=e,c.mdxType="string"==typeof e?e:r,l[1]=c;for(var b=2;b=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var c=r.a.createContext({}),d=function(e){var t=r.a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},u=function(e){var t=d(e.components);return r.a.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},b=r.a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,i=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=d(n),b=o,y=u["".concat(i,".").concat(b)]||u[b]||p[b]||a;return n?r.a.createElement(y,l(l({ref:t},c),{},{components:n})):r.a.createElement(y,l({ref:t},c))}));function y(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=b;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var c=2;c\n")),Object(o.b)("p",null,"Login to your UAA with the ",Object(o.b)("inlineCode",{parentName:"p"},"admin")," client:"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"uaac token client get admin -s \n")),Object(o.b)("p",null,"Next, check the configuration of your Client - for example, for the ",Object(o.b)("inlineCode",{parentName:"p"},"cf")," client:"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"uaac client get cf\n")),Object(o.b)("p",null,"You'll get the current configuration - there are two properties of interest ",Object(o.b)("inlineCode",{parentName:"p"},"redirect_uri")," and ",Object(o.b)("inlineCode",{parentName:"p"},"authorized_grant_types"),"."),Object(o.b)("blockquote",null,Object(o.b)("p",{parentName:"blockquote"},"Note: The following commands will overwrite existing values for the settings specified. To keep the existing values along with the new value include them in the new value as a comma-separated list.")),Object(o.b)("p",null,"The ",Object(o.b)("inlineCode",{parentName:"p"},"redirect_uri")," value should contain the Stratos redirect URI. If not update the Client with:"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"uaac client update cf --redirect_uri https://HOST.DOMAIN/pp/v1/auth/sso_login_callback\n")),Object(o.b)("p",null,"The ",Object(o.b)("inlineCode",{parentName:"p"},"authorized_grant_types")," value should contain ",Object(o.b)("inlineCode",{parentName:"p"},"authorization_code"),". If not update the Client with:"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"uaac client update cf --authorized_grant_types authorization_code\n")),Object(o.b)("h2",{id:"adding-a-stratos-sso-state-whitelist"},"Adding a Stratos SSO State Whitelist"),Object(o.b)("p",null,"When SSO has been configured Stratos's log in request will contain a URL that tells SSO where to return to. When using a browser this is automatically populated. To avoid situations where this can be hijacked or called separately an SSO ",Object(o.b)("inlineCode",{parentName:"p"},"state")," whitelist can be provided via the environment variable ",Object(o.b)("inlineCode",{parentName:"p"},"SSO_WHITELIST"),". This is a comma separated list. For example..."),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"SSO_WHITELIST=https://your.domain/*\n")),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"SSO_WHITELIST=https://your.domain/*,https://your.other.domain/*\n")),Object(o.b)("p",null,"When set, any requests to log in with a different ",Object(o.b)("inlineCode",{parentName:"p"},"state")," will be denied."),Object(o.b)("p",null,"In order for the SSO ",Object(o.b)("inlineCode",{parentName:"p"},"state")," to match an entry from the whitelist the schema, hostname, port and path must match exactly. A wildcard ",Object(o.b)("inlineCode",{parentName:"p"},"*")," can be provided for the path to match anything."))}u.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return p})),n.d(t,"b",(function(){return h}));var a=n(0),r=n.n(a);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function c(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=r.a.createContext({}),u=function(e){var t=r.a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p=function(e){var t=u(e.components);return r.a.createElement(s.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},d=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,i=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),p=u(n),d=a,h=p["".concat(i,".").concat(d)]||p[d]||b[d]||o;return n?r.a.createElement(h,c(c({ref:t},s),{},{components:n})):r.a.createElement(h,c({ref:t},s))}));function h(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=d;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c.mdxType="string"==typeof e?e:a,i[1]=c;for(var s=2;s + + + + + +Page Not Found | STRATOS + + + + + +
+

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

+ + + + + \ No newline at end of file diff --git a/website/site-dist/48.42bd91cb.js b/website/site-dist/48.42bd91cb.js new file mode 100644 index 0000000000..0e19861321 --- /dev/null +++ b/website/site-dist/48.42bd91cb.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[48,49],{147:function(e,t,n){"use strict";n.r(t);n(12);var a=n(0),r=n.n(a),o=n(149),l=n(150),c=n(46),s=n(155),i=n(2),u=n(151),p=n(161),m=n(164),d=n(165),y=n(166),h=n(163),b=n(152),f=n(154),g=n(104),v=n.n(g);const k=(e,t)=>"link"===e.type?((e,t)=>{const n=e=>e.endsWith("/")?e:e+"/";return n(e)===n(t)})(e.href,t):"category"===e.type&&e.items.some(e=>k(e,t));function j({item:e,onItemClick:t,collapsible:n,activePath:o,...l}){const{items:c,label:s}=e,p=k(e,o),m=function(e){const t=Object(a.useRef)(e);return Object(a.useEffect)(()=>{t.current=e},[e]),t.current}(p),[d,y]=Object(a.useState)(()=>!!n&&(!p&&e.collapsed));Object(a.useEffect)(()=>{p&&!m&&d&&y(!1)},[p,m,d]);const h=Object(a.useCallback)(e=>{e.preventDefault(),y(e=>!e)},[y]);return 0===c.length?null:r.a.createElement("li",{className:Object(u.a)("menu__list-item",{"menu__list-item--collapsed":d}),key:s},r.a.createElement("a",Object(i.a)({className:Object(u.a)("menu__link",{"menu__link--sublist":n,"menu__link--active":n&&p,[v.a.menuLinkText]:!n}),onClick:n?h:void 0,href:n?"#!":void 0},l),s),r.a.createElement("ul",{className:"menu__list"},c.map(e=>r.a.createElement(E,{tabIndex:d?"-1":"0",key:e.label,item:e,onItemClick:t,collapsible:n,activePath:o}))))}function O({item:e,onItemClick:t,activePath:n,collapsible:a,...o}){const{href:l,label:c}=e,s=k(e,n);return r.a.createElement("li",{className:"menu__list-item",key:c},r.a.createElement(b.a,Object(i.a)({className:Object(u.a)("menu__link",{"menu__link--active":s}),to:l},Object(f.a)(l)?{isNavLink:!0,exact:!0,onClick:t}:{target:"_blank",rel:"noreferrer noopener"},o),c))}function E(e){switch(e.item.type){case"category":return r.a.createElement(j,e);case"link":default:return r.a.createElement(O,e)}}var N=function(e){const[t,n]=Object(a.useState)(!1),{siteConfig:{themeConfig:{navbar:{title:o,hideOnScroll:c=!1}={}}}={},isClient:s}=Object(l.a)(),{logoLink:f,logoLinkProps:g,logoImageUrl:k,logoAlt:j}=Object(y.a)(),{isAnnouncementBarClosed:O}=Object(p.a)(),{scrollY:N}=Object(h.a)(),{docsSidebars:C,path:w,sidebar:x,sidebarCollapsible:P}=e;Object(m.a)(t);const _=Object(d.a)();if(Object(a.useEffect)(()=>{_===d.b.desktop&&n(!1)},[_]),!x)return null;const T=C[x];if(!T)throw new Error(`Cannot find the sidebar "${x}" in the sidebar config!`);return r.a.createElement("div",{className:Object(u.a)(v.a.sidebar,{[v.a.sidebarWithHideableNavbar]:c})},c&&r.a.createElement(b.a,Object(i.a)({tabIndex:"-1",className:v.a.sidebarLogo,to:f},g),null!=k&&r.a.createElement("img",{key:s,src:k,alt:j}),null!=o&&r.a.createElement("strong",null,o)),r.a.createElement("div",{className:Object(u.a)("menu","menu--responsive",v.a.menu,{"menu--show":t,[v.a.menuWithAnnouncementBar]:!O&&0===N})},r.a.createElement("button",{"aria-label":t?"Close Menu":"Open Menu","aria-haspopup":"true",className:"button button--secondary button--sm menu__button",type:"button",onClick:()=>{n(!t)}},t?r.a.createElement("span",{className:Object(u.a)(v.a.sidebarMenuIcon,v.a.sidebarMenuCloseIcon)},"\xd7"):r.a.createElement("svg",{"aria-label":"Menu",className:v.a.sidebarMenuIcon,xmlns:"http://www.w3.org/2000/svg",height:24,width:24,viewBox:"0 0 32 32",role:"img",focusable:"false"},r.a.createElement("title",null,"Menu"),r.a.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))),r.a.createElement("ul",{className:"menu__list"},T.map(e=>r.a.createElement(E,{key:e.label,item:e,onItemClick:e=>{e.target.blur(),n(!1)},collapsible:P,activePath:w})))))},C={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","at-rule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]},w={Prism:n(35).a,theme:C};function x(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function P(){return(P=Object.assign||function(e){for(var t=1;t0&&e[n-1]===t?e:e.concat(t)},L=function(e,t){var n=e.plain,a=Object.create(null),r=e.styles.reduce((function(e,n){var a=n.languages,r=n.style;return a&&!a.includes(t)||n.types.forEach((function(t){var n=P({},e[t],r);e[t]=n})),e}),a);return r.root=n,r.plain=P({},n,{backgroundColor:null}),r};function D(e,t){var n={};for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&-1===t.indexOf(a)&&(n[a]=e[a]);return n}var I=function(e){function t(){for(var t=this,n=[],a=arguments.length;a--;)n[a]=arguments[a];e.apply(this,n),x(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var n=e.theme?L(e.theme,e.language):void 0;return t.themeDict=n})),x(this,"getLineProps",(function(e){var n=e.key,a=e.className,r=e.style,o=P({},D(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),l=t.getThemeDict(t.props);return void 0!==l&&(o.style=l.plain),void 0!==r&&(o.style=void 0!==o.style?P({},o.style,r):r),void 0!==n&&(o.key=n),a&&(o.className+=" "+a),o})),x(this,"getStyleForToken",(function(e){var n=e.types,a=e.empty,r=n.length,o=t.getThemeDict(t.props);if(void 0!==o){if(1===r&&"plain"===n[0])return a?{display:"inline-block"}:void 0;if(1===r&&!a)return o[n[0]];var l=a?{display:"inline-block"}:{},c=n.map((function(e){return o[e]}));return Object.assign.apply(Object,[l].concat(c))}})),x(this,"getTokenProps",(function(e){var n=e.key,a=e.className,r=e.style,o=e.token,l=P({},D(e,["key","className","style","token"]),{className:"token "+o.types.join(" "),children:o.content,style:t.getStyleForToken(o),key:void 0});return void 0!==r&&(l.style=void 0!==l.style?P({},l.style,r):r),void 0!==n&&(l.key=n),a&&(l.className+=" "+a),l}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,n=e.language,a=e.code,r=e.children,o=this.getThemeDict(this.props),l=t.languages[n];return r({tokens:function(e){for(var t=[[]],n=[e],a=[0],r=[e.length],o=0,l=0,c=[],s=[c];l>-1;){for(;(o=a[l]++)0?u:["plain"],i=p):(u=S(u,p.type),p.alias&&(u=S(u,p.alias)),i=p.content),"string"==typeof i){var m=i.split(_),d=m.length;c.push({types:u,content:m[0]});for(var y=1;y{const{siteConfig:{themeConfig:{prism:e={}}}}=Object(l.a)(),{isDarkTheme:t}=Object(W.a)(),n=e.theme||R,a=e.darkTheme||n;return t?a:n},z=n(105),J=n.n(z);const U=/{([\d,-]+)}/,H=(e=["js","jsBlock","jsx","python","html"])=>{const t={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},python:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}},n=["highlight-next-line","highlight-start","highlight-end"].join("|"),a=e.map(e=>`(?:${t[e].start}\\s*(${n})\\s*${t[e].end})`).join("|");return new RegExp(`^\\s*(?:${a})\\s*$`)},X=/title=".*"/;var Y=({children:e,className:t,metastring:n})=>{const{siteConfig:{themeConfig:{prism:o={}}}}=Object(l.a)(),[c,s]=Object(a.useState)(!1),[p,m]=Object(a.useState)(!1);Object(a.useEffect)(()=>{m(!0)},[]);const d=Object(a.useRef)(null);let y=[],h="";const b=F();if(n&&U.test(n)){const e=n.match(U)[1];y=$.a.parse(e).filter(e=>e>0)}n&&X.test(n)&&(h=n.match(X)[0].split("title=")[1].replace(/"+/g,""));let f=t&&t.replace(/language-/,"");!f&&o.defaultLanguage&&(f=o.defaultLanguage);let g=e.replace(/\n$/,"");if(0===y.length&&void 0!==f){let t="";const n=(e=>{switch(e){case"js":case"javascript":case"ts":case"typescript":return H(["js","jsBlock"]);case"jsx":case"tsx":return H(["js","jsBlock","jsx"]);case"html":return H(["js","jsBlock","html"]);case"python":case"py":return H(["python"]);default:return H()}})(f),a=e.replace(/\n$/,"").split("\n");let r;for(let e=0;ee||t,void 0)){case"highlight-next-line":t+=o+",";break;case"highlight-start":r=o;break;case"highlight-end":t+=`${r}-${o-1},`}a.splice(e,1)}else e+=1}y=$.a.parse(t),g=a.join("\n")}const v=()=>{A()(g),s(!0),setTimeout(()=>s(!1),2e3)};return r.a.createElement(I,Object(i.a)({},w,{key:p,theme:b,code:g,language:f}),({className:e,style:t,tokens:n,getLineProps:a,getTokenProps:o})=>r.a.createElement(r.a.Fragment,null,h&&r.a.createElement("div",{style:t,className:J.a.codeBlockTitle},h),r.a.createElement("div",{className:J.a.codeBlockContent},r.a.createElement("button",{ref:d,type:"button","aria-label":"Copy code to clipboard",className:Object(u.a)(J.a.copyButton,{[J.a.copyButtonWithTitle]:h}),onClick:v},c?"Copied":"Copy"),r.a.createElement("div",{tabIndex:"0",className:Object(u.a)(e,J.a.codeBlock,{[J.a.codeBlockWithTitle]:h})},r.a.createElement("div",{className:J.a.codeBlockLines,style:t},n.map((e,t)=>{1===e.length&&""===e[0].content&&(e[0].content="\n");const n=a({line:e,key:t});return y.includes(t+1)&&(n.className=n.className+" docusaurus-highlight-code-line"),r.a.createElement("div",Object(i.a)({key:t},n),e.map((e,t)=>r.a.createElement("span",Object(i.a)({key:t},o({token:e,key:t})))))}))))))},q=(n(106),n(107)),G=n.n(q);var K=e=>function({id:t,...n}){const{siteConfig:{themeConfig:{navbar:{hideOnScroll:a=!1}={}}={}}={}}=Object(l.a)();return t?r.a.createElement(e,n,r.a.createElement("a",{"aria-hidden":"true",tabIndex:"-1",className:Object(u.a)("anchor",{[G.a.enhancedAnchor]:!a}),id:t}),n.children,r.a.createElement("a",{"aria-hidden":"true",tabIndex:"-1",className:"hash-link",href:"#"+t,title:"Direct link to heading"},"#")):r.a.createElement(e,n)},Q=n(108),V=n.n(Q),Z={code:e=>{const{children:t}=e;return"string"==typeof t?t.includes("\n")?r.a.createElement(Y,e):r.a.createElement("code",e):t},a:e=>/\.[^./]+$/.test(e.href)?r.a.createElement("a",e):r.a.createElement(b.a,e),pre:e=>r.a.createElement("div",Object(i.a)({className:V.a.mdxCodeBlock},e)),h1:K("h1"),h2:K("h2"),h3:K("h3"),h4:K("h4"),h5:K("h5"),h6:K("h6")},ee=n(157),te=n(162),ne=n(109),ae=n.n(ne);t.default=function(e){const{route:t,docsMetadata:n,location:a}=e,i=t.routes.find(e=>Object(te.a)(a.pathname,e))||{},{permalinkToSidebar:u,docsSidebars:p,version:m}=n,d=u[i.path],{siteConfig:{themeConfig:y={}}={},isClient:h}=Object(l.a)(),{sidebarCollapsible:b=!0}=y;return 0===Object.keys(i).length?r.a.createElement(ee.default,e):r.a.createElement(s.a,{version:m,key:h},r.a.createElement("div",{className:ae.a.docPage},d&&r.a.createElement("div",{className:ae.a.docSidebarContainer,role:"complementary"},r.a.createElement(N,{docsSidebars:p,path:i.path,sidebar:d,sidebarCollapsible:b})),r.a.createElement("main",{className:ae.a.docMainContainer},r.a.createElement(o.a,{components:Z},Object(c.a)(t.routes)))))}},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return p})),n.d(t,"b",(function(){return y}));var a=n(0),r=n.n(a);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function c(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var i=r.a.createContext({}),u=function(e){var t=r.a.useContext(i),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p=function(e){var t=u(e.components);return r.a.createElement(i.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},d=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,i=s(e,["components","mdxType","originalType","parentName"]),p=u(n),d=a,y=p["".concat(l,".").concat(d)]||p[d]||m[d]||o;return n?r.a.createElement(y,c(c({ref:t},i),{},{components:n})):r.a.createElement(y,c({ref:t},i))}));function y(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,l=new Array(o);l[0]=d;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:a,l[1]=c;for(var i=2;i{const n=document.createElement("textarea"),a=document.activeElement;n.value=e,n.setAttribute("readonly",""),n.style.contain="strict",n.style.position="absolute",n.style.left="-9999px",n.style.fontSize="12pt";const r=document.getSelection();let o=!1;r.rangeCount>0&&(o=r.getRangeAt(0)),t.append(n),n.select(),n.selectionStart=0,n.selectionEnd=e.length;let l=!1;try{l=document.execCommand("copy")}catch(c){}return n.remove(),o&&(r.removeAllRanges(),r.addRange(o)),a&&a.focus(),l};e.exports=a,e.exports.default=a},176:function(e,t){e.exports.parse=function(e){var t=e.split(",").map((function(e){return function(e){if(/^-?\d+$/.test(e))return parseInt(e,10);var t;if(t=e.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){var n=t[1],a=t[2],r=t[3];if(n&&r){var o=[],l=(n=parseInt(n))<(r=parseInt(r))?1:-1;"-"!=a&&".."!=a&&"\u2025"!=a||(r+=l);for(var c=n;c!=r;c+=l)o.push(c);return o}}return[]}(e)}));return 0===t.length?[]:1===t.length?Array.isArray(t[0])?t[0]:t:t.reduce((function(e,t){return Array.isArray(e)||(e=[e]),Array.isArray(t)||(t=[t]),e.concat(t)}))}}}]); \ No newline at end of file diff --git a/website/site-dist/49.6e8e7afa.js b/website/site-dist/49.6e8e7afa.js new file mode 100644 index 0000000000..7ee4fda615 --- /dev/null +++ b/website/site-dist/49.6e8e7afa.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[49],{157:function(e,t,a){"use strict";a.r(t);var n=a(0),o=a.n(n),l=a(155);t.default=function(){return o.a.createElement(l.a,{title:"Page Not Found"},o.a.createElement("div",{className:"container margin-vert--xl"},o.a.createElement("div",{className:"row"},o.a.createElement("div",{className:"col col--6 col--offset-3"},o.a.createElement("h1",{className:"hero__title"},"Page Not Found"),o.a.createElement("p",null,"We could not find what you were looking for."),o.a.createElement("p",null,"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))}}}]); \ No newline at end of file diff --git a/website/site-dist/4f58b3e2.08f32a31.js b/website/site-dist/4f58b3e2.08f32a31.js new file mode 100644 index 0000000000..4c119b628a --- /dev/null +++ b/website/site-dist/4f58b3e2.08f32a31.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[18],{118:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return c})),n.d(t,"metadata",(function(){return i})),n.d(t,"rightToc",(function(){return l})),n.d(t,"default",(function(){return u}));var a=n(2),r=n(6),o=(n(0),n(149)),c={title:"Frontend Tests",sidebar_label:"Tests"},i={id:"developer/frontend-tests",isDocsHomePage:!1,title:"Frontend Tests",description:"Test",source:"@site/docs/developer/frontend-tests.md",permalink:"/docs/developer/frontend-tests",editUrl:"https://github.com/cloudfoundry/stratos/edit/master/website/docs/developer/frontend-tests.md",sidebar_label:"Tests",sidebar:"docs",previous:{title:"Frontend Development",permalink:"/docs/developer/frontend"},next:{title:"Backend Development",permalink:"/docs/developer/backend"}},l=[{value:"Test",id:"test",children:[{value:"Lint",id:"lint",children:[]},{value:"Unit tests",id:"unit-tests",children:[]},{value:"End-to-end tests",id:"end-to-end-tests",children:[]},{value:"Code Climate",id:"code-climate",children:[]},{value:"Stratos Continue Integration",id:"stratos-continue-integration",children:[]}]}],s={rightToc:l};function u(e){var t=e.components,n=Object(r.a)(e,["components"]);return Object(o.b)("wrapper",Object(a.a)({},s,n,{components:t,mdxType:"MDXLayout"}),Object(o.b)("h2",{id:"test"},"Test"),Object(o.b)("h3",{id:"lint"},"Lint"),Object(o.b)("p",null,"Run ",Object(o.b)("inlineCode",{parentName:"p"},"npm run lint")," to execute tslint lint checking."),Object(o.b)("h3",{id:"unit-tests"},"Unit tests"),Object(o.b)("p",null,"Run ",Object(o.b)("inlineCode",{parentName:"p"},"npm test")," to execute the unit tests via ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"https://karma-runner.github.io"}),"Karma"),". Coverage information can be found in ",Object(o.b)("inlineCode",{parentName:"p"},"./coverage")),Object(o.b)("p",null,"To execute an individual package run ",Object(o.b)("inlineCode",{parentName:"p"},"ng test "),". To execute the tests again automatically on code changes add ",Object(o.b)("inlineCode",{parentName:"p"},"--watch=true")),Object(o.b)("blockquote",null,Object(o.b)("p",{parentName:"blockquote"},Object(o.b)("strong",{parentName:"p"},"NOTE")," npm test will search for chrome on your path. If this is not so please set an env var CHROME_BIN pointing to your executable\n(chromium is fine too).")),Object(o.b)("h3",{id:"end-to-end-tests"},"End-to-end tests"),Object(o.b)("p",null,"Run ",Object(o.b)("inlineCode",{parentName:"p"},"npm run e2e")," to execute the end-to-end tests via ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"http://www.protractortest.org/"}),"Protractor"),"."),Object(o.b)("p",null,"Run ",Object(o.b)("inlineCode",{parentName:"p"},"npm run e2e-dev")," to execute end-to-end tests against a locally running instance on ",Object(o.b)("inlineCode",{parentName:"p"},"https://localhost:4200")),Object(o.b)("p",null,"More information on the E2E tests and pre-requisites for running them is available here - ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"/docs/developer/developers-guide-e2e-tests"}),"E2E Tests"),"."),Object(o.b)("h3",{id:"code-climate"},"Code Climate"),Object(o.b)("p",null,"We use ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"https://codeclimate.com/github/cloudfoundry-incubator/stratos"}),"Code Climate")," to check for general code quality issues. This executes against Pull\nRequests on creation/push."),Object(o.b)("h4",{id:"running-code-climate-locally"},"Running Code Climate locally"),Object(o.b)("blockquote",null,Object(o.b)("p",{parentName:"blockquote"},"Generally we would not advise doing this and just rely on the code climate gate to run when pull requests are submitted")),Object(o.b)("p",null,"To run locally see instructions ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"https://github.com/codeclimate/codeclimate"}),"here")," to install Code Climate CLI\nand engine via docker. Once set ensure you're in the root of the project and execute the following (it may take a while)"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"codeclimate analyze\n")),Object(o.b)("blockquote",null,Object(o.b)("p",{parentName:"blockquote"},Object(o.b)("strong",{parentName:"p"},"NOTE")," Unfortunately this highlights all current issues and not those that are the diff between any master and feature branch. Analyze\ncan be ran against a single/sub set of files, again with all current issues, but a little more digestible.")),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"codeclimate analyze \n")),Object(o.b)("p",null,"In a feature branch to compare files that have changed to master, for instance, use the following"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"git checkout feature-branch-A\ncodeclimate analyze $(git diff --name-only master)\n")),Object(o.b)("p",null,"You can also run the above command via npm"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"npm run climate\n")),Object(o.b)("h3",{id:"stratos-continue-integration"},"Stratos Continue Integration"),Object(o.b)("p",null,"For each new pull request and any subsequent pushes to it the following actions are executed"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Code quality analysis via Code Climate - ",Object(o.b)("a",Object(a.a)({parentName:"li"},{href:"https://codeclimate.com/"}),"https://codeclimate.com/")),Object(o.b)("li",{parentName:"ul"},"Jenkins CI run, covering..",Object(o.b)("ul",{parentName:"li"},Object(o.b)("li",{parentName:"ul"},"Frontend lint check"),Object(o.b)("li",{parentName:"ul"},"Backend lint check"),Object(o.b)("li",{parentName:"ul"},"Frontend unit tests"),Object(o.b)("li",{parentName:"ul"},"Backend unit tests"),Object(o.b)("li",{parentName:"ul"},"End to end tests"))),Object(o.b)("li",{parentName:"ul"},"Security anaylsis via Snyk - ",Object(o.b)("a",Object(a.a)({parentName:"li"},{href:"https://snyk.io/"}),"https://snyk.io/"))))}u.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return b})),n.d(t,"b",(function(){return m}));var a=n(0),r=n.n(a);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=r.a.createContext({}),u=function(e){var t=r.a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},b=function(e){var t=u(e.components);return r.a.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},d=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),b=u(n),d=a,m=b["".concat(c,".").concat(d)]||b[d]||p[d]||o;return n?r.a.createElement(m,i(i({ref:t},s),{},{components:n})):r.a.createElement(m,i({ref:t},s))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,c=new Array(o);c[0]=d;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i.mdxType="string"==typeof e?e:a,c[1]=i;for(var s=2;s=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=o.a.createContext({}),p=function(e){var t=o.a.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},l=function(e){var t=p(e.components);return o.a.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,c=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),l=p(n),f=r,m=l["".concat(c,".").concat(f)]||l[f]||d[f]||i;return n?o.a.createElement(m,a(a({ref:t},u),{},{components:n})):o.a.createElement(m,a({ref:t},u))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,c=new Array(i);c[0]=f;var a={};for(var s in t)hasOwnProperty.call(t,s)&&(a[s]=t[s]);a.originalType=e,a.mdxType="string"==typeof e?e:r,c[1]=a;for(var u=2;u=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=o.a.createContext({}),u=function(e){var t=o.a.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},p=function(e){var t=u(e.components);return o.a.createElement(l.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},m=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,i=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),p=u(r),m=n,b=p["".concat(i,".").concat(m)]||p[m]||d[m]||a;return r?o.a.createElement(b,c(c({ref:t},l),{},{components:r})):o.a.createElement(b,c({ref:t},l))}));function b(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:n,i[1]=c;for(var l=2;l=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=r.a.createContext({}),d=function(e){var t=r.a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=d(e.components);return r.a.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},b=r.a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,s=c(e,["components","mdxType","originalType","parentName"]),u=d(n),b=o,m=u["".concat(l,".").concat(b)]||u[b]||p[b]||a;return n?r.a.createElement(m,i(i({ref:t},s),{},{components:n})):r.a.createElement(m,i({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,l=new Array(a);l[0]=b;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i.mdxType="string"==typeof e?e:o,l[1]=i;for(var s=2;s=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=i.a.createContext({}),u=function(e){var t=i.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},d=function(e){var t=u(e.components);return i.a.createElement(l.Provider,{value:t},e.children)},h={inlineCode:"code",wrapper:function(e){var t=e.children;return i.a.createElement(i.a.Fragment,{},t)}},p=i.a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,a=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),d=u(n),p=o,b=d["".concat(a,".").concat(p)]||d[p]||h[p]||r;return n?i.a.createElement(b,s(s({ref:t},l),{},{components:n})):i.a.createElement(b,s({ref:t},l))}));function b(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,a=new Array(r);a[0]=p;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:o,a[1]=s;for(var l=2;linclude-relations, inline-relations-depth)",id:"relations-include-relations-inline-relations-depth",children:[]},{value:"Pagination (page, results-per-page)",id:"pagination-page-results-per-page",children:[]},{value:"Sorting (order-direction)",id:"sorting-order-direction",children:[]},{value:"Queries (q)",id:"queries-q",children:[]}]},{value:"Scaling",id:"scaling",children:[]},{value:"API Examples",id:"api-examples",children:[{value:"User visits applications lists... and then views an application summary page",id:"user-visits-applications-lists-and-then-views-an-application-summary-page",children:[]},{value:"User directly visits application summary page",id:"user-directly-visits-application-summary-page",children:[]},{value:"User sits on application summary view",id:"user-sits-on-application-summary-view",children:[]},{value:"User navigates to space summary view from cf summary view and org summary view",id:"user-navigates-to-space-summary-view-from-cf-summary-view-and-org-summary-view",children:[]},{value:"User directly visits an space summary view",id:"user-directly-visits-an-space-summary-view",children:[]},{value:"Random click around (fetching data)",id:"random-click-around-fetching-data",children:[]}]},{value:"V2 Specifics",id:"v2-specifics",children:[{value:"Sorting/Filtering",id:"sortingfiltering",children:[]},{value:"Inline Relations",id:"inline-relations",children:[]},{value:"Cloud Foundry, Organisation and Space Summary Information",id:"cloud-foundry-organisation-and-space-summary-information",children:[]}]},{value:"V2 Summary",id:"v2-summary",children:[{value:"Current v2 Issues",id:"current-v2-issues",children:[]},{value:"Critical v2 Features",id:"critical-v2-features",children:[]}]}],l={rightToc:d};function p(e){var a=e.components,t=Object(r.a)(e,["components"]);return Object(i.b)("wrapper",Object(n.a)({},l,t,{components:a,mdxType:"MDXLayout"}),Object(i.b)("h1",{id:"cloud-foundry-api-v2-feature-usage"},"Cloud Foundry API v2 Feature Usage"),Object(i.b)("ol",null,Object(i.b)("li",{parentName:"ol"},Object(i.b)("a",Object(n.a)({parentName:"li"},{href:"#High-Level-Stratos-Concepts"}),"High Level Stratos Concepts")),Object(i.b)("li",{parentName:"ol"},Object(i.b)("a",Object(n.a)({parentName:"li"},{href:"#API-Parameters"}),"API Parameters")),Object(i.b)("li",{parentName:"ol"},Object(i.b)("a",Object(n.a)({parentName:"li"},{href:"#API-Examples"}),"API Examples")),Object(i.b)("li",{parentName:"ol"},Object(i.b)("a",Object(n.a)({parentName:"li"},{href:"#V2-Specifics"}),"V2 Specifics")),Object(i.b)("li",{parentName:"ol"},Object(i.b)("a",Object(n.a)({parentName:"li"},{href:"#V2-Summary"}),"V2 Summary"))),Object(i.b)("h2",{id:"high-level-stratos-concepts"},"High Level Stratos Concepts"),Object(i.b)("p",null,"Stratos exercises many features of the Cloud Foundry v2 API, in order to understand these a general knowledge of Stratos concepts is required"),Object(i.b)("h3",{id:"lists"},"Lists"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Collections of entities are presenting using a list component, which covers table and card grid views."),Object(i.b)("li",{parentName:"ul"},"Lists can be",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"Sorted by a number of fields"),Object(i.b)("li",{parentName:"ul"},"Filtered by text or Cloud Foundry, Organisation or Space (some lists contain entities from multiple cloud foundries)"),Object(i.b)("li",{parentName:"ul"},"Paginated"))),Object(i.b)("li",{parentName:"ul"},"Example 1 - Applications List",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"Applications sorting by application name, instances, disk quota, memory and creation date"),Object(i.b)("li",{parentName:"ul"},"Applications filtered by name, cf, organisation or space"))),Object(i.b)("li",{parentName:"ul"},"Example 2 - Organisation List",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"Orgs sorted by name or creation date"),Object(i.b)("li",{parentName:"ul"},"Orgs filtered by name"))),Object(i.b)("li",{parentName:"ul"},"In order to support a decent level of filtering and sorting we often fetch all entities and store them locally (these are referred to as local lists)"),Object(i.b)("li",{parentName:"ul"},"Alternatively, in places where we don't need as much rich filtering and sorting, or the amount of entities are too high, we use standard\npage requests and whatever sorting and filtering is available (these are referred to as non-local lists)")),Object(i.b)("h3",{id:"entity-relations--validation"},"Entity Relations & Validation"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Cloud Foundry entities (organisation, route, service plan, etc) are stored client side in an entity store"),Object(i.b)("li",{parentName:"ul"},"The console provides methods to fetch an entity or collection of entities from the store. At this time Stratos states if any of the\nentity's relations are required, for instance when fetching an organisation the spaces and services properties may be required"),Object(i.b)("li",{parentName:"ul"},"The console checks if the required entity/s exist in the store.",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"If they're missing they're then fetched via the API, including any required relationships"),Object(i.b)("li",{parentName:"ul"},"If they exist in the store their relations are checked. Any missing relations are fetched using the ",Object(i.b)("inlineCode",{parentName:"li"},"_url")," property"))),Object(i.b)("li",{parentName:"ul"},"This means we fetch the minimum amount of data, and can ensure we have the required data when it's needed"),Object(i.b)("li",{parentName:"ul"},"If the relationship is one to many then all of the missing entities are fetched, even if this involved more than one request."),Object(i.b)("li",{parentName:"ul"},"Example 1",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"To filter the applications in the applications list by cf/org/space we fetch a list of organisations and state each org must have it's\nspaces property",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"The resulting org entity will only have the space's relation, each space will have no other relation"))),Object(i.b)("li",{parentName:"ul"},"The user navigates to a space summary screen"),Object(i.b)("li",{parentName:"ul"},"The space summary screen states the space should contain applications, service instances, space quota, service binding, etc"),Object(i.b)("li",{parentName:"ul"},"Entity validation will fetch the missing relations using the ",Object(i.b)("inlineCode",{parentName:"li"},"_url")," of the relation"))),Object(i.b)("li",{parentName:"ul"},"Examples 2",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"To show the applications in the applications list we fetch a list of apps with the following relations",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"application - space"),Object(i.b)("li",{parentName:"ul"},"space - organisation"),Object(i.b)("li",{parentName:"ul"},"application - route"))),Object(i.b)("li",{parentName:"ul"},"The user navigates to a application summary screen"),Object(i.b)("li",{parentName:"ul"},"The application summary screen states the application should have",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"application - route"),Object(i.b)("li",{parentName:"ul"},"application - space"),Object(i.b)("li",{parentName:"ul"},"application - stack"),Object(i.b)("li",{parentName:"ul"},"application - service binding"),Object(i.b)("li",{parentName:"ul"},"route - domain"),Object(i.b)("li",{parentName:"ul"},"space - organisation"))),Object(i.b)("li",{parentName:"ul"},"Entity validation will then usually* fetch the two missing entities stack and domain",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"Depending on what entities currently exist in the store having been fetched by other calls")))))),Object(i.b)("h3",{id:"summary-stats"},"Summary Stats"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Some pages show summary information to do with an entity (Application, Organisation, Service, etc)"),Object(i.b)("li",{parentName:"ul"},"Some of these will show stats where only the count of entities are required"),Object(i.b)("li",{parentName:"ul"},"Example 1 - Service Summary",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"No# of service instances"),Object(i.b)("li",{parentName:"ul"},"No# of service plans"))),Object(i.b)("li",{parentName:"ul"},"Example 2 - Organisation Summary",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"No# of spaces in organisation"),Object(i.b)("li",{parentName:"ul"},"No# of applications in organisation"),Object(i.b)("li",{parentName:"ul"},"No# of application instances in organisation"),Object(i.b)("li",{parentName:"ul"},"No# of User in organisation"),Object(i.b)("li",{parentName:"ul"},"Memory usage (total memory of running apps) out of organisation memory quota"),Object(i.b)("li",{parentName:"ul"},"Routes in organisation out of organisation root quota"),Object(i.b)("li",{parentName:"ul"},"Private domains out of organisation private domain quota"),Object(i.b)("li",{parentName:"ul"},"Service instance count out of organisation instance quota")))),Object(i.b)("h3",{id:"application-state"},"Application State"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"In most places where we present an application we show a summary state"),Object(i.b)("li",{parentName:"ul"},"Examples",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"Pending")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"Offline while Updating")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"Deployed - No Instances")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"Deployed - Scaling App")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"Deployed - Crashing")))),Object(i.b)("li",{parentName:"ul"},"Summary state is a combination of",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"App ",Object(i.b)("inlineCode",{parentName:"li"},"state")),Object(i.b)("li",{parentName:"ul"},"App ",Object(i.b)("inlineCode",{parentName:"li"},"package_state")),Object(i.b)("li",{parentName:"ul"},"App ",Object(i.b)("inlineCode",{parentName:"li"},"package_updated_at")),Object(i.b)("li",{parentName:"ul"},"App ",Object(i.b)("inlineCode",{parentName:"li"},"instances")),Object(i.b)("li",{parentName:"ul"},"App Stats instances collection"))),Object(i.b)("li",{parentName:"ul"},"To present these kind of states we need to call the ",Object(i.b)("inlineCode",{parentName:"li"},"/stats")," endpoint for each app. This means on the Applications list we cannot sort by\napp state (there could be thousands of apps).")),Object(i.b)("h3",{id:"users-roles-and-permissions"},"Users, Roles and Permissions"),Object(i.b)("p",null,"The console user will connect to a CF with their personal CF credentials. These credentials dictate not only what they're allowed to do in\nthe console but also how we have to fetch data."),Object(i.b)("h4",{id:"listing-users--their-roles"},"Listing users & their roles"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"We provide a way for users of all types to view a list of users (at the cf, organisation and space levels) and their roles"),Object(i.b)("li",{parentName:"ul"},"We have to fetch this information differently between CF administrators with certain scopes and non-cf administrators"),Object(i.b)("li",{parentName:"ul"},"CF Admins can list users via ",Object(i.b)("inlineCode",{parentName:"li"},"/users")),Object(i.b)("li",{parentName:"ul"},"Non-CF admins cannot access ",Object(i.b)("inlineCode",{parentName:"li"},"/users")," list (aside from themselves)",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"At the CF level we do not show a list of all users"),Object(i.b)("li",{parentName:"ul"},"At the org level we show all users via ",Object(i.b)("inlineCode",{parentName:"li"},"organizations/${guid}/users")),Object(i.b)("li",{parentName:"ul"},"At the space level we show all users via ",Object(i.b)("inlineCode",{parentName:"li"},"spaces/${guid}/user_roles"))))),Object(i.b)("h4",{id:"permissions"},"Permissions"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Permissions are dictated by the admin/non-admin state of the connected user, cf feature flags and all of the users organisation and space roles"),Object(i.b)("li",{parentName:"ul"},"For CF admins we skip fetching roles, as their admin state overrides roles"),Object(i.b)("li",{parentName:"ul"},"For non-admins we hit each ",Object(i.b)("inlineCode",{parentName:"li"},"users//")," endpoint, there's a lot of duplicated data (orgs and spaces) here")),Object(i.b)("h2",{id:"api-parameters"},"API Parameters"),Object(i.b)("h3",{id:"relations-include-relations-inline-relations-depth"},"Relations (",Object(i.b)("inlineCode",{parentName:"h3"},"include-relations"),", ",Object(i.b)("inlineCode",{parentName:"h3"},"inline-relations-depth"),")"),Object(i.b)("p",null,"In order to support the entity validation process described above we make heavy use of the generic ",Object(i.b)("inlineCode",{parentName:"p"},"inline-relations-depth")," and ",Object(i.b)("inlineCode",{parentName:"p"},"include-relations")," parameters"),Object(i.b)("blockquote",null,Object(i.b)("p",{parentName:"blockquote"},"Note - ",Object(i.b)("inlineCode",{parentName:"p"},"exclude-relations")," is not used.")),Object(i.b)("p",null,"When we show the Space summary page the following space relations are required"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"space - routes"),Object(i.b)("li",{parentName:"ul"},"space - quota"),Object(i.b)("li",{parentName:"ul"},"space - service instances"),Object(i.b)("li",{parentName:"ul"},"service instance - service bindings"),Object(i.b)("li",{parentName:"ul"},"service bindings - application"),Object(i.b)("li",{parentName:"ul"},"space - applications")),Object(i.b)("h4",{id:"include-relations"},"include-relations"),Object(i.b)("p",null,"Given the space summary example, on a fresh load of the console directly to a space summary page equates to"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{}),"include-relations=routes,space_quota_definition,service_instances,service_bindings,app,apps\n")),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("p",{parentName:"li"},"As there's only one way to define the parent in a include-relations string any child relation with the same name in both parent and\nchild will be fetched. For example if space contained an ",Object(i.b)("inlineCode",{parentName:"p"},"apps")," property and one of it's children also had an ",Object(i.b)("inlineCode",{parentName:"p"},"apps")," property both will be\nfetched.")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("p",{parentName:"li"},"If a relationship contains a list of entities, and that list contains more than 50, the collection is missing in the API response. As per\nnon-list entities we use the ",Object(i.b)("inlineCode",{parentName:"p"},"_url")," value to fetch these, however will automatically fetch all values and not just the first page (just\nlike a local-list)."))),Object(i.b)("h4",{id:"inline-relations-depth"},"inline-relations-depth"),Object(i.b)("p",null,"The inline depth, up to 2, is calculated by the number of chained relations. In the space summary example above the actual depth is 3\n(space --\x3e service instance --\x3e service binding --\x3e application). As 2 is the maximum the last relation of binding --\x3e application is\nmissing in the api response. If the missing application is not already in the store it's fetched by the ",Object(i.b)("inlineCode",{parentName:"p"},"_url")," value."),Object(i.b)("h3",{id:"pagination-page-results-per-page"},"Pagination (",Object(i.b)("inlineCode",{parentName:"h3"},"page"),", ",Object(i.b)("inlineCode",{parentName:"h3"},"results-per-page"),")"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Pagination is either controlled",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"locally (local lists)",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"We fetch all entities by setting results-per-page to maximum and iterate through every page"),Object(i.b)("li",{parentName:"ul"},"Paging is then handled client side"))),Object(i.b)("li",{parentName:"ul"},"remotely (non-local lists)",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"We fetch pages that haven't been fetched before in a page size determined by the user")))))),Object(i.b)("h3",{id:"sorting-order-direction"},"Sorting (",Object(i.b)("inlineCode",{parentName:"h3"},"order-direction"),")"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"The CF API only supports sorting on a very small subset of properties such as creation_date and event timestamp"),Object(i.b)("li",{parentName:"ul"},"This is only used when sorting non-local lists (see pagination section above)")),Object(i.b)("h3",{id:"queries-q"},"Queries (",Object(i.b)("inlineCode",{parentName:"h3"},"q"),")"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"We have the functionality to use these per list, however are rarely used",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"The Application Events non-local list uses these to define the actee (the app)"),Object(i.b)("li",{parentName:"ul"},"The Applications list uses these to filter by org/space when there are too many applications to handle locally"),Object(i.b)("li",{parentName:"ul"},"Fetch all service instances with a service bindings"),Object(i.b)("li",{parentName:"ul"},"Fetch all service instances with a service plan"))),Object(i.b)("li",{parentName:"ul"},"Using ",Object(i.b)("inlineCode",{parentName:"li"},"q")," to filter via org and space is sometimes possible, sometimes not",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"A route is created in a space, however cannot filter routes via space"),Object(i.b)("li",{parentName:"ul"},"Service brokers can be filtered by space, however not by organisation")))),Object(i.b)("h2",{id:"scaling"},"Scaling"),Object(i.b)("p",null,"We've recently started updating a lot of features to be sensitive of CFs with large collections of entities. This involves..."),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Local Lists will check the total number of results before fetching them all. If too high we refuse to show the table/cards."),Object(i.b)("li",{parentName:"ul"},"Counts of entities are done via ",Object(i.b)("inlineCode",{parentName:"li"},"results-per-page")," of 1 and ",Object(i.b)("inlineCode",{parentName:"li"},"total_results")," instead of fetching all entities"),Object(i.b)("li",{parentName:"ul"},"Inline relations of one to many, and the count might be too high, are removed and the functionality that requires them reworked",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"For instance space --\x3e routes"),Object(i.b)("li",{parentName:"ul"},"Some will remain the same, for instance service --\x3e service plans")))),Object(i.b)("h2",{id:"api-examples"},"API Examples"),Object(i.b)("h3",{id:"user-visits-applications-lists-and-then-views-an-application-summary-page"},"User visits applications lists... and then views an application summary page"),Object(i.b)("details",null,Object(i.b)("summary",null,"Applications List"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{}),"organizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=1&include-relations=spaces\napps?order-direction=asc&order-direction-field=creation&page=1&results-per-page=100&inline-relations-depth=2&include-relations=space,organization,routes\norganizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/fe72bac0-6d22-495c-a1d8-67180461f52f/stats?order-direction=desc&order-direction-field=index&results-per-page=5\n"))),Object(i.b)("details",null,Object(i.b)("summary",null,"Nav to Application Summary"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{}),"apps/ca47f757-caf7-4142-803b-a577c995869f/env?order-direction=desc&order-direction-field=name&results-per-page=5&page=1\nstacks/83eaeaa0-dbd0-4ff9-bb28-50adbbce4e78\nshared_domains/a09e5ec7-ddc4-476d-a431-a45af446d2f2\napps/ca47f757-caf7-4142-803b-a577c995869f/service_bindings?results-per-page=100&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f/summary\n"))),Object(i.b)("h3",{id:"user-directly-visits-application-summary-page"},"User directly visits application summary page"),Object(i.b)("details",null,Object(i.b)("summary",null,"Calls"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{}),"apps/ca47f757-caf7-4142-803b-a577c995869f/env?order-direction=desc&order-direction-field=name&results-per-page=5&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f?inline-relations-depth=2&include-relations=stack,space,organization,routes,domain,service_bindings\napps/ca47f757-caf7-4142-803b-a577c995869f/summary\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1\n"))),Object(i.b)("h3",{id:"user-sits-on-application-summary-view"},"User sits on application summary view"),Object(i.b)("details",null,Object(i.b)("summary",null,"The following is repeated"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{}),"apps/ca47f757-caf7-4142-803b-a577c995869f?inline-relations-depth=2&include-relations=stack,space,organization,routes,domain,service_bindings\napps/ca47f757-caf7-4142-803b-a577c995869f/summary\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1\n"))),Object(i.b)("h3",{id:"user-navigates-to-space-summary-view-from-cf-summary-view-and-org-summary-view"},"User navigates to space summary view from cf summary view and org summary view"),Object(i.b)("details",null,Object(i.b)("summary",null,"Cf Summary View"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{}),"shared_domains?results-per-page=100&page=1\norganizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps\nusers?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=1&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1\nusers/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3\norganizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2\norganizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1&inline-relations-depth=1&include-relations=routes,service_instances,apps\n"))),Object(i.b)("details",null,Object(i.b)("summary",null,"Nav to Org Summary View"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{}),"organizations/78ee5f44-0a33-4544-9fa8-acb0de7155ce/users?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1\nusers/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3\n"))),Object(i.b)("details",null,Object(i.b)("summary",null,"Nav to Space Summary View"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{}),"service_instances/f2656532-e77c-46fa-a2cb-595e6957e6f6/service_bindings?results-per-page=100&page=1&inline-relations-depth=1&include-relations=app\nservice_instances/99e91478-b485-469f-a653-a3dd5bc84b4f/service_bindings?results-per-page=100&page=1&inline-relations-depth=2&include-relations=app\nservice_instances/3db6b84a-71eb-4c16-b9ff-6e71f7981dab/service_bindings?results-per-page=100&page=1&inline-relations-depth=2&include-relations=app\nservice_instances/b7d411a1-5ab4-4159-a34a-73b9a9b4e733/service_bindings?results-per-page=100&page=1&inline-relations-depth=2&include-relations=app\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/user_roles?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1\nusers/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3\n"))),Object(i.b)("h3",{id:"user-directly-visits-an-space-summary-view"},"User directly visits an space summary view"),Object(i.b)("details",null,Object(i.b)("summary",null,"Calls"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{}),"shared_domains?results-per-page=100&page=1\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9?inline-relations-depth=2&include-relations=routes,space_quota_definition,service_instances,service_bindings,app,apps\norganizations/78ee5f44-0a33-4544-9fa8-acb0de7155ce?inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/user_roles?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=1&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces\norganizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps\nusers?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1\nusers/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1\nusers/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3\norganizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps\norganizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1&inline-relations-depth=1&include-relations=routes,service_instances,apps\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\n"))),Object(i.b)("h3",{id:"random-click-around-fetching-data"},"Random click around (fetching data)"),Object(i.b)("details",null,Object(i.b)("summary",null,"This shows a whole range of calls we make, all `GET`s"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{}),"organizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=1&include-relations=spaces\napps?order-direction=asc&order-direction-field=creation&page=1&results-per-page=100&inline-relations-depth=2&include-relations=space,organization,routes\norganizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=1&include-relations=spaces\norganizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1\napps?order-direction=asc&order-direction-field=creation&page=2&results-per-page=100&inline-relations-depth=2&include-relations=space,organization,routes\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/fe72bac0-6d22-495c-a1d8-67180461f52f/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/ca47f757-caf7-4142-803b-a577c995869f/env?order-direction=desc&order-direction-field=name&results-per-page=5&page=1\nstacks/83eaeaa0-dbd0-4ff9-bb28-50adbbce4e78\nshared_domains/a09e5ec7-ddc4-476d-a431-a45af446d2f2\napps/ca47f757-caf7-4142-803b-a577c995869f/service_bindings?results-per-page=100&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f/summary\nshared_domains?results-per-page=100&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f/service_bindings?results-per-page=100&page=1&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=app,service_instance,service,service_plan\nservices/aebc001e-cf51-4d09-b5cd-d1d024685797\nservice_instances/b7d411a1-5ab4-4159-a34a-73b9a9b4e733/service_bindings?results-per-page=100&page=1&inline-relations-depth=1&include-relations=app\nservices/aebc001e-cf51-4d09-b5cd-d1d024685797/service_plans?results-per-page=100&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f?inline-relations-depth=2&include-relations=stack,space,organization,routes,domain,service_bindings\nevents?q=actee:ca47f757-caf7-4142-803b-a577c995869f&q=actee:ca47f757-caf7-4142-803b-a577c995869f&order-direction=desc&order-direction-field=timestamp&results-per-page=5&page=1\nevents?order-direction=desc&order-direction-field=timestamp&q=actee:ca47f757-caf7-4142-803b-a577c995869f&results-per-page=9&page=1\nservices?page=1&results-per-page=100&order-direction=desc&order-direction-field=label&inline-relations-depth=2&include-relations=service_plans\nservice_brokers?page=1&results-per-page=100&order-direction=desc&order-direction-field=name\nservice_instances?page=1&results-per-page=100&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service\nservice_instances?page=1&results-per-page=100&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service\norganizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps\nusers?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=1&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces\norganizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1\nusers/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2\norganizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1&inline-relations-depth=1&include-relations=routes,service_instances,apps\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3\napps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\nconfig/feature_flags?page=1&order-direction=desc&order-direction-field=name&results-per-page=25\nbuildpacks?page=1&results-per-page=100&order-direction=desc&order-direction-field=position\nstacks?page=1&results-per-page=100&order-direction=desc&order-direction-field=name\nsecurity_groups?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&inline-relations-depth=1&include-relations=spaces\napps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\norganizations/78ee5f44-0a33-4544-9fa8-acb0de7155ce/users?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1\nusers/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/user_roles?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=1&results-per-page=5&order-direction=desc&order-direction-field=creation\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1\nusers/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=2&results-per-page=5&order-direction=desc&order-direction-field=creation\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=1&results-per-page=5&order-direction=asc&order-direction-field=creation\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/service_instances?page=1&results-per-page=5&order-direction=desc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/service_instances?page=1&results-per-page=5&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=1&order-direction=desc&order-direction-field=creation&inline-relations-depth=1&include-relations=domain,apps\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=2&order-direction=desc&order-direction-field=creation&inline-relations-depth=2&include-relations=domain,apps\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=1&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=domain,apps\n"))),Object(i.b)("details",null,Object(i.b)("summary",null,"Same as above but sorted"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{}),"apps?order-direction=asc&order-direction-field=creation&page=1&results-per-page=100&inline-relations-depth=2&include-relations=space,organization,routes\napps?order-direction=asc&order-direction-field=creation&page=2&results-per-page=100&inline-relations-depth=2&include-relations=space,organization,routes\napps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/ca47f757-caf7-4142-803b-a577c995869f?inline-relations-depth=2&include-relations=stack,space,organization,routes,domain,service_bindings\napps/ca47f757-caf7-4142-803b-a577c995869f/env?order-direction=desc&order-direction-field=name&results-per-page=5&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f/service_bindings?results-per-page=100&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f/service_bindings?results-per-page=100&page=1&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=app,service_instance,service,service_plan\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1\napps/ca47f757-caf7-4142-803b-a577c995869f/summary\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5\napps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&results-per-page=5\napps/fe72bac0-6d22-495c-a1d8-67180461f52f/stats?order-direction=desc&order-direction-field=index&results-per-page=5\nbuildpacks?page=1&results-per-page=100&order-direction=desc&order-direction-field=position\nconfig/feature_flags?page=1&order-direction=desc&order-direction-field=name&results-per-page=25\nevents?order-direction=desc&order-direction-field=timestamp&q=actee:ca47f757-caf7-4142-803b-a577c995869f&results-per-page=9&page=1\nevents?q=actee:ca47f757-caf7-4142-803b-a577c995869f&q=actee:ca47f757-caf7-4142-803b-a577c995869f&order-direction=desc&order-direction-field=timestamp&results-per-page=5&page=1\norganizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=1&include-relations=spaces\norganizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps\norganizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=1&include-relations=spaces\norganizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps\norganizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1\norganizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1&inline-relations-depth=1&include-relations=routes,service_instances,apps\norganizations/78ee5f44-0a33-4544-9fa8-acb0de7155ce/users?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces\nsecurity_groups?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&inline-relations-depth=1&include-relations=spaces\nservice_brokers?page=1&results-per-page=100&order-direction=desc&order-direction-field=name\nservice_instances?page=1&results-per-page=100&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service\nservice_instances?page=1&results-per-page=100&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service\nservice_instances/b7d411a1-5ab4-4159-a34a-73b9a9b4e733/service_bindings?results-per-page=100&page=1&inline-relations-depth=1&include-relations=app\nservices?page=1&results-per-page=100&order-direction=desc&order-direction-field=label&inline-relations-depth=2&include-relations=service_plans\nservices/aebc001e-cf51-4d09-b5cd-d1d024685797\nservices/aebc001e-cf51-4d09-b5cd-d1d024685797/service_plans?results-per-page=100&page=1\nshared_domains?results-per-page=100&page=1\nshared_domains/a09e5ec7-ddc4-476d-a431-a45af446d2f2\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=1&results-per-page=5&order-direction=asc&order-direction-field=creation\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=1&results-per-page=5&order-direction=desc&order-direction-field=creation\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=2&results-per-page=5&order-direction=desc&order-direction-field=creation\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=1&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=domain,apps\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=1&order-direction=desc&order-direction-field=creation&inline-relations-depth=1&include-relations=domain,apps\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=2&order-direction=desc&order-direction-field=creation&inline-relations-depth=2&include-relations=domain,apps\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/service_instances?page=1&results-per-page=5&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/service_instances?page=1&results-per-page=5&order-direction=desc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service\nspaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/user_roles?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces\nstacks?page=1&results-per-page=100&order-direction=desc&order-direction-field=name\nstacks/83eaeaa0-dbd0-4ff9-bb28-50adbbce4e78\nusers?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=1&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3\nusers/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2\nusers/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2\nusers/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1\nusers/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1\nusers/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1\n"))),Object(i.b)("h2",{id:"v2-specifics"},"V2 Specifics"),Object(i.b)("h3",{id:"sortingfiltering"},"Sorting/Filtering"),Object(i.b)("p",null,"As described elsewhere Stratos lists can be sorted and/or filtered. To support this we try to make use of sorting and filtering via the API,\nhowever in many cases this is not possible resulting in Stratos fetching the entire list and handling sorting, filtering and pagination\nlocally. Obviously this is a major issue when there are large numbers of rows."),Object(i.b)("p",null,"Below is a list of each endpoint and the type of sorting / filtering we use with them. Items marked in ",Object(i.b)("strong",{parentName:"p"},Object(i.b)("em",{parentName:"strong"},"bold and italic"))," are missing\nfrom the v2 api."),Object(i.b)("table",null,Object(i.b)("thead",{parentName:"table"},Object(i.b)("tr",{parentName:"thead"},Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Endpoint"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Sorted Locally"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Sorted via API"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Filtered Locally"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Filtered via API"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Used API Pagination"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Desired Sort"))),Object(i.b)("tbody",{parentName:"table"},Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${guid}/stats")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},"index in array")),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"state"))),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"usage.mem"))),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"usage.disk"))),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"usage.cpu"))),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"uptime")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"state")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${guid}/routes")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"host"))),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"port")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${guid}/service_bindings")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name"))),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"instances"))),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"disk_quota"))),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"memory"))),", ",Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"name"),", ",Object(i.b)("inlineCode",{parentName:"td"},"organisation"),", ",Object(i.b)("inlineCode",{parentName:"td"},"space")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"organisation"),", ",Object(i.b)("inlineCode",{parentName:"td"},"space")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"organizations/${orgGuid}/spaces")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name"))),", ",Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"name")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"organizations")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"name"),", ",Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"name")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"organizations/${guid}/users")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"username")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"username")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"name")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces/${spaceGuid}/routes")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Yes"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},"Host")))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces/${spaceGuid}/apps")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Yes"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},"Name")),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},"Status")))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces/${spaceGuid}/services")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces/${spaceGuid}/service_instances")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Yes"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},"Instance name")),",",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},"Service name")),",",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},"Service Plan name")),",")),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Other endpoints"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"buildpacks")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"position"))),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name"))),", ",Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"config/feature_flags")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"events")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"timestamp")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"actee"),", ",Object(i.b)("inlineCode",{parentName:"td"},"type")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Yes"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"security_groups")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name"))),", ",Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"service_brokers")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"service_instances")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"name"),", ",Object(i.b)("inlineCode",{parentName:"td"},"organisation"),", ",Object(i.b)("inlineCode",{parentName:"td"},"space")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"service_instances/${guid}/service_bindings")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"service_plan_visibilities")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"service_plan_guid")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"service_plan/${guid}/service_instances")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"services")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"label"))),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"active"))),", ",Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"bindable")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"label")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"services/${guid}/service_plans")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name"))),", ",Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"stacks")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name"))),", ",Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name")))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"users")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("strong",{parentName:"td"},Object(i.b)("em",{parentName:"strong"},Object(i.b)("inlineCode",{parentName:"em"},"name"))),", ",Object(i.b)("inlineCode",{parentName:"td"},"created_at")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"name")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))))),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},Object(i.b)("em",{parentName:"strong"},"``"))),Object(i.b)("h3",{id:"inline-relations"},"Inline Relations"),Object(i.b)("p",null,"Below is a list of all the inline relations we use for each of the more fleshed out v3 endpoints of apps, spaces and organisations."),Object(i.b)("blockquote",null,Object(i.b)("p",{parentName:"blockquote"},"Note - Some of the one to many relations will be removed in the near future to support scaling, see ",Object(i.b)("a",Object(n.a)({parentName:"p"},{href:"#Scaling"}),"Scaling"))),Object(i.b)("h4",{id:"application"},"Application"),Object(i.b)("table",null,Object(i.b)("thead",{parentName:"table"},Object(i.b)("tr",{parentName:"thead"},Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Endpoint"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Inline Relations"))),Object(i.b)("tbody",{parentName:"table"},Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"app --\x3e route"),Object(i.b)("li",null,"app --\x3e space"),Object(i.b)("li",null,"space --\x3e org")))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${appGuid}")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"app --\x3e route"),Object(i.b)("li",null,"route --\x3e domain"),Object(i.b)("li",null,"app --\x3e space"),Object(i.b)("li",null,"space --\x3e org"),Object(i.b)("li",null,"app --\x3e stack"),Object(i.b)("li",null,"app --\x3e service binding")))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${appGuid}/routes")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"route --\x3e domain"),Object(i.b)("li",null,"route --\x3e application")))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${appGuid}/service_bindings")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"service binding --\x3e service instance")))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${appGuid}/stats")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-")),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${appGuid}/env")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-")),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${appGuid}/summary")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-")),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${appGuid}/routes/${routeGuid}")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-")),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${appGuid}/instances/${index}")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-")),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"apps/${appGuid}/restage")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-")))),Object(i.b)("h4",{id:"organisation"},"Organisation"),Object(i.b)("table",null,Object(i.b)("thead",{parentName:"table"},Object(i.b)("tr",{parentName:"thead"},Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Endpoint"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Inline Relations"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(i.b)("tbody",{parentName:"table"},Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"organizations/${orgGuid}")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"org --\x3e space"),Object(i.b)("li",null,"space --\x3e service instances"),Object(i.b)("li",null,"space --\x3e apps"),Object(i.b)("li",null,"space --\x3e routes"),Object(i.b)("li",null,"org --\x3e domain"),Object(i.b)("li",null,"org --\x3e quota definition"),Object(i.b)("li",null,"org --\x3e private domains"),Object(i.b)("li",null,"org --\x3e users"),Object(i.b)("li",null,"org --\x3e managers"),Object(i.b)("li",null,"org --\x3e billing managers"),Object(i.b)("li",null,"org --\x3e auditors"))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"organizations/${orgGuid}/spaces")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"space --\x3e apps"),Object(i.b)("li",null,"space --\x3e service instances"),Object(i.b)("li",null,"space --\x3e space quota"))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"organizations")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"org --\x3e space"),Object(i.b)("li",null,"space --\x3e service instances"),Object(i.b)("li",null,"space --\x3e apps"),Object(i.b)("li",null,"space --\x3e routes"),Object(i.b)("li",null,"org --\x3e domain"),Object(i.b)("li",null,"org --\x3e quota definition"),Object(i.b)("li",null,"org --\x3e private domains"))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"organizations/${orgGuid}/users")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"user --\x3e orgs"),Object(i.b)("li",null,"user --\x3e audited orgs"),Object(i.b)("li",null,"user --\x3e managed orgs"),Object(i.b)("li",null,"user --\x3e billing manager"),Object(i.b)("li",null,"user --\x3e space dev"),Object(i.b)("li",null,"user --\x3e space manager"),Object(i.b)("li",null,"user --\x3e space auditor"))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"We can't switch to ",Object(i.b)("inlineCode",{parentName:"td"},"/users?organization_guid=${guid}")," as this fails for no cf admins")))),Object(i.b)("h4",{id:"space"},"Space"),Object(i.b)("table",null,Object(i.b)("thead",{parentName:"table"},Object(i.b)("tr",{parentName:"thead"},Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Endpoint"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Inline Relations"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Notes"))),Object(i.b)("tbody",{parentName:"table"},Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Note currently used, spaces are either fetchined inline with an org or via the org spaces endpoint")),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces/${spaceGuid}")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"space --\x3e org"),Object(i.b)("li",null,"space --\x3e domains"),Object(i.b)("li",null,"space --\x3e routes"),Object(i.b)("li",null,"route --\x3e domain"),Object(i.b)("li",null,"route --\x3e applications"))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces/${spaceGuid}/routes")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"route --\x3e domain"),Object(i.b)("li",null,"route --\x3e application"))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces/${spaceGuid}/apps")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces/${spaceGuid}/user_roles")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"-"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces/${spaceGuid}/services")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"service --\x3e service plan"))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("inlineCode",{parentName:"td"},"spaces/${spaceGuid}/service_instances")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("ul",null,Object(i.b)("li",null,"service instance --\x3e service bindings"),Object(i.b)("li",null,"service binding --\x3e application"),Object(i.b)("li",null,"service instance --\x3e service plan"),Object(i.b)("li",null,"service instance --\x3e space"),Object(i.b)("li",null,"space --\x3e org"),Object(i.b)("li",null,"service instance --\x3e service"))),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))))),Object(i.b)("h4",{id:"others"},"Others"),Object(i.b)("p",null,"The include-relations property is populated by walking our relationship tree, so for a complete and exhaustive list of all possible\nrelations please see the ",Object(i.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/blob/master/src/frontend/app/store/helpers/entity-factory.ts"}),Object(i.b)("inlineCode",{parentName:"a"},"entity-factory.ts")),"."),Object(i.b)("p",null,"In terms of api requests we also make use of..."),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/buildpacks")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/config/feature_flags")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/events")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/routes")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/security_groups")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/services")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/service_bindings")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/service_brokers")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/service_instances")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/service_plan_visibilities")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/service_plan")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/shared_domains")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/stacks")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"/users"))),Object(i.b)("h3",{id:"cloud-foundry-organisation-and-space-summary-information"},"Cloud Foundry, Organisation and Space Summary Information"),Object(i.b)("p",null,"In the ",Object(i.b)("inlineCode",{parentName:"p"},"Cloud Foundry")," section of Stratos we show summary pages at the CF, Org and Space levels. These consist of information from the core\ncf/org/space but also statistics such as number of users or memory used within that cf/org/space.\nSome of these can be fetched by ",Object(i.b)("inlineCode",{parentName:"p"},"results-per-page")," of 1 and ",Object(i.b)("inlineCode",{parentName:"p"},"total_results"),", however others are derived and require fetching a large amount\nof additional data, either inline with the org/space or as separate requests (",Object(i.b)("inlineCode",{parentName:"p"},"Memory usage")," is the count of memory per instance per app).\nBelow is a table showing the stats at each level. The counts are respective of that level (number of routes in that specific cf, org or space)"),Object(i.b)("table",null,Object(i.b)("thead",{parentName:"table"},Object(i.b)("tr",{parentName:"thead"},Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Stat/Info"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"CF Summary"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Org Summary"),Object(i.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Space Summary"))),Object(i.b)("tbody",{parentName:"table"},Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"No. of Apps"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep"))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"No. of App Instances"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep"))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"No. of Organisations"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"No. of Users"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep"))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"Memory Usage"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep"))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"No. of Routes"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep"))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"No. of Private Domains"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}))),Object(i.b)("tr",{parentName:"tbody"},Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"No. of Service Instances"),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null})),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep")),Object(i.b)("td",Object(n.a)({parentName:"tr"},{align:null}),Object(i.b)("em",{parentName:"td"},"yep"))))),Object(i.b)("h2",{id:"v2-summary"},"V2 Summary"),Object(i.b)("h3",{id:"current-v2-issues"},"Current v2 Issues"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Most lists will fetch all entities up front to provide a reasonable level of sorting and filtering",Object(i.b)("ul",{parentName:"li"},Object(i.b)("li",{parentName:"ul"},"API provides limited sorting and filtering capabilities"),Object(i.b)("li",{parentName:"ul"},"Sorting is mostly just on ",Object(i.b)("inlineCode",{parentName:"li"},"creation_date")),Object(i.b)("li",{parentName:"ul"},"Filtering sometimes contains org, space and name, but not all",Object(i.b)("blockquote",{parentName:"li"},Object(i.b)("p",{parentName:"blockquote"},"Desired - Lists of entities can be sorted or filtered on any top level property"))))),Object(i.b)("li",{parentName:"ul"},"Calculated numerical summary stats (number of applications in an organisation, cumulative total of memory from running apps in an\norganisation, number of users etc) requires fetching all entities of a certain type. This can be quite a costly set of requests.",Object(i.b)("blockquote",{parentName:"li"},Object(i.b)("p",{parentName:"blockquote"},"Desired - ",Object(i.b)("inlineCode",{parentName:"p"},"counts")," API which, given a filter, could sum up a selection of numerical properties of collection of entities. Some of this\nmay already be possible by making individual requests with ",Object(i.b)("inlineCode",{parentName:"p"},"results-per-page=1")," & ",Object(i.b)("inlineCode",{parentName:"p"},"total_results")," and ",Object(i.b)("inlineCode",{parentName:"p"},"q")," filters, however a neat way to\ncombine these into a single request would be awesome. For instance in a single request, for an org, fetch total number of apps, app\ninstances, routes, etc)"))),Object(i.b)("li",{parentName:"ul"},"Determining an informative application state requires an additional request to the ",Object(i.b)("inlineCode",{parentName:"li"},"application//stats")," endpoint.",Object(i.b)("blockquote",{parentName:"li"},Object(i.b)("p",{parentName:"blockquote"},"Desired - It would massively improve Stratos performance if the APIs to list applications and retrieve a specific application could\nreturn the app stats for the application(s). If this is not possibly, an app stats call that can return stats for all running\napplications would help."))),Object(i.b)("li",{parentName:"ul"},"Fetching a list of users for non-admins can be expensive if there are many organizations.",Object(i.b)("blockquote",{parentName:"li"},Object(i.b)("p",{parentName:"blockquote"},"Desired - In an ideal world non-admins would be able to hit ",Object(i.b)("inlineCode",{parentName:"p"},"/users")," and get the same response as hitting all if their visible\n",Object(i.b)("inlineCode",{parentName:"p"},"organization/${guid}/users")," endpoints."))),Object(i.b)("li",{parentName:"ul"},"The user entities that are returned by the ",Object(i.b)("inlineCode",{parentName:"li"},"/users")," request contain a lot of duplicated organisation and space entities.",Object(i.b)("blockquote",{parentName:"li"},Object(i.b)("p",{parentName:"blockquote"},"Desired - Entities are listed in a common bucket and referenced by guid inline. Think this might be how v3 works"))),Object(i.b)("li",{parentName:"ul"},"The ",Object(i.b)("inlineCode",{parentName:"li"},"_url")," in a user entity can only be called by an administrator or by the same user",Object(i.b)("blockquote",{parentName:"li"},Object(i.b)("p",{parentName:"blockquote"},"Desired - URL behaves as per the ",Object(i.b)("inlineCode",{parentName:"p"},"/users")," suggestion above the response contains the organisations that are visible to the user that\ncalls the url"))),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"include-relations")," works by specifying the name of the child property. If the ",Object(i.b)("inlineCode",{parentName:"li"},"inline-relations-depth")," is greater than one this can lead\nrelations being fetched that might not actually be required",Object(i.b)("blockquote",{parentName:"li"},Object(i.b)("p",{parentName:"blockquote"},"Desired - Minor nice to have. Be able to specify relations like ",Object(i.b)("inlineCode",{parentName:"p"},"include-relations=application-route,route-domain"))))),Object(i.b)("h3",{id:"critical-v2-features"},"Critical v2 Features"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"Where exposed, sort order and filtering via ",Object(i.b)("inlineCode",{parentName:"li"},"q")),Object(i.b)("li",{parentName:"ul"},"Arbitrary entity relations can be fetched or not fetched. The way we store and retrieve entity/s would break down without this generic process"),Object(i.b)("li",{parentName:"ul"},"The API provides a url (",Object(i.b)("inlineCode",{parentName:"li"},"_url"),") to fetch missing entity relations. As per relations, without this we'd need a process to\ngenerically make up the url for any given relationships")))}p.isMDXComponent=!0},149:function(e,a,t){"use strict";t.d(a,"a",(function(){return b})),t.d(a,"b",(function(){return g}));var n=t(0),r=t.n(n);function i(e,a,t){return a in e?Object.defineProperty(e,a,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[a]=t,e}function s(e,a){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);a&&(n=n.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),t.push.apply(t,n)}return t}function c(e){for(var a=1;a=0||(r[t]=e[t]);return r}(e,a);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=r.a.createContext({}),p=function(e){var a=r.a.useContext(l),t=a;return e&&(t="function"==typeof e?e(a):c(c({},a),e)),t},b=function(e){var a=p(e.components);return r.a.createElement(l.Provider,{value:a},e.children)},o={inlineCode:"code",wrapper:function(e){var a=e.children;return r.a.createElement(r.a.Fragment,{},a)}},u=r.a.forwardRef((function(e,a){var t=e.components,n=e.mdxType,i=e.originalType,s=e.parentName,l=d(e,["components","mdxType","originalType","parentName"]),b=p(t),u=n,g=b["".concat(s,".").concat(u)]||b[u]||o[u]||i;return t?r.a.createElement(g,c(c({ref:a},l),{},{components:t})):r.a.createElement(g,c({ref:a},l))}));function g(e,a){var t=arguments,n=a&&a.mdxType;if("string"==typeof e||n){var i=t.length,s=new Array(i);s[0]=u;var c={};for(var d in a)hasOwnProperty.call(a,d)&&(c[d]=a[d]);c.originalType=e,c.mdxType="string"==typeof e?e:n,s[1]=c;for(var l=2;l")),Object(r.b)("p",null,"Where ",Object(r.b)("inlineCode",{parentName:"p"},"")," is the default domain configured for your Cloud Foundry cluster."),Object(r.b)("p",null,"To login use the following credentials detailed ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"access.md"}),"here"),"."),Object(r.b)("p",null,"If you run into issues, please refer to the ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"#troubleshooting"}),"Troubleshooting Guide")," below."),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"The console will pre-configure the host Cloud Foundry endpoint. No other CF instance should be registered unless the instructions in\nthe section ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"#associate-cloud-foundry-database-service"}),"Associate Cloud Foundry database service")," are followed.\nAll other deployment methods (helm, docker all-in-one, etc) allow the registration of multiple CF instances by default.")),Object(r.b)("p",null,"Note:"),Object(r.b)("ol",null,Object(r.b)("li",{parentName:"ol"},"You need the cf CLI command line tool installed and available on the path."),Object(r.b)("li",{parentName:"ol"},"You need to have configured the cf cli to point to your Cloud Foundry cluster, to be authenticated with your credentials and to be targeted at the organization and space where you want the console application be created."),Object(r.b)("li",{parentName:"ol"},"You may need to configure Application Security Groups on your Cloud Foundry Cluster in order that Stratos can communicate with the Cloud Foundry API. See ",Object(r.b)("a",Object(o.a)({parentName:"li"},{href:"#application-security-groups"}),"below")," for more information."),Object(r.b)("li",{parentName:"ol"},"The Stratos Console will automatically detect the API endpoint for your Cloud Foundry. To do so, it relies on the ",Object(r.b)("inlineCode",{parentName:"li"},"cf_api_url")," value inside the ",Object(r.b)("inlineCode",{parentName:"li"},"VCAP_APPLICATION")," environment variable. If this is not provided by your Cloud Foundry platform, then you must manually update the application manifest as described ",Object(r.b)("a",Object(o.a)({parentName:"li"},{href:"#console-fails-to-start"}),"below"),".")),Object(r.b)("h3",{id:"running-stratos-in-production-environments"},"Running Stratos in Production Environments"),Object(r.b)("p",null,"Please be aware of the following when running Stratos in a production environment:"),Object(r.b)("h4",{id:"configure-a-session-store-secret"},"Configure a Session Store Secret"),Object(r.b)("p",null,"Stratos uses a Session Store Secret to protect the user session cookie. We recommend that you set your own value for this secret - choosing an alphanumeric string of your choice."),Object(r.b)("p",null,"You can configure this secret by editing the application manifest and adding to the ",Object(r.b)("inlineCode",{parentName:"p"},"env")," section, e.g."),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"applications:\n- name: console\n ... memory, disk settings here\n env:\n SESSION_STORE_SECRET: \n")),Object(r.b)("h4",{id:"pre-configure-uaa-client-used-for-user-invites"},"Pre-configure UAA client used for user invites"),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"You can skip this step and configure any CFs invite clients via the Stratos UI.")),Object(r.b)("p",null," To set the UAA client for user invites, supply the client id and client secret as environment variables as shown below:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"INVITE_USER_CLIENT_ID=\nINVITE_USER_CLIENT_SECRET=\n")),Object(r.b)("p",null,"This will set the the UAA client and UAA secret used to invite users for the default CF only."),Object(r.b)("p",null,"See the ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"../guides/admin/invite-user-guide"}),"invite users guide")," for more information about user invites in Stratos."),Object(r.b)("h4",{id:"use-of-the-default-embedded-sqlite-database"},"Use of the Default Embedded SQLite Database"),Object(r.b)("p",null,"We do not recommend deploying Stratos to a production environment using the default embedded SQLite Database. Instead we recommend creating\nand binding a database service instance to Stratos - for more information see ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"db-migration"}),"here"),"."),Object(r.b)("h3",{id:"deploy-stratos-from-source"},"Deploy Stratos from source"),Object(r.b)("p",null,"To do so, ",Object(r.b)("inlineCode",{parentName:"p"},"clone")," the ",Object(r.b)("strong",{parentName:"p"},"stratos")," repository, ",Object(r.b)("inlineCode",{parentName:"p"},"cd")," into the newly cloned repository and ",Object(r.b)("inlineCode",{parentName:"p"},"push")," to Cloud Foundry. This can be done with:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"git clone https://github.com/cloudfoundry/stratos\ncd stratos\ngit checkout tags/stable -b stable\n./build/store-git-metadata.sh\ncf push\n")),Object(r.b)("p",null,"If the cf push exceeds the time allowed see the instructions ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"#pre-building-the-ui"}),"here")),Object(r.b)("h4",{id:"pre-building-the-ui"},"Pre-building the UI"),Object(r.b)("p",null,"Due to the memory usage of the Angular compiler (see below), when deployed to Cloud Foundry via ",Object(r.b)("inlineCode",{parentName:"p"},"cf push"),", Stratos does not use AOT (Ahead-of-Time) compilation."),Object(r.b)("p",null,"If you wish to enable AOT or reduce the push time, you can pre-build the UI before pushing."),Object(r.b)("p",null,"This can be done with:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"git clone https://github.com/cloudfoundry/stratos\ncd stratos\nnpm install\nnpm run prebuild-ui\ncf push\n")),Object(r.b)("p",null,"You will need a recent version of Node installed locally to do this."),Object(r.b)("p",null,"The ",Object(r.b)("inlineCode",{parentName:"p"},"prebuild-ui")," npm script performs a build of the front-end UI and then zips up the resulting folder into a package named ",Object(r.b)("inlineCode",{parentName:"p"},"stratos-frontend-prebuild.zip"),". The Stratos buildpack will unpack this zip file and use its contents instead of building the UI during staging, when this file is present."),Object(r.b)("h4",{id:"memory-usage"},"Memory Usage"),Object(r.b)("p",null,"The Stratos Cloud Foundry ",Object(r.b)("inlineCode",{parentName:"p"},"manifest.yml")," states that the application requires\n",Object(r.b)("inlineCode",{parentName:"p"},"1512MB")," of memory. This is required during the build process of the\napplication since building an angular2 app is a memory intensive process. The\nmemory limit can be scaled down after the app has been pushed, using the cf CLI."),Object(r.b)("h3",{id:"deploy-stratos-from-docker-image"},"Deploy Stratos from docker image"),Object(r.b)("p",null,"Deploy Stratos using the ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://hub.docker.com/r/splatform/stratos"}),Object(r.b)("inlineCode",{parentName:"a"},"splatform/stratos"))," docker image"),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},Object(r.b)("strong",{parentName:"p"},"NOTE:")," Your Cloud Foundry must have docker support ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://docs.cloudfoundry.org/adminguide/docker.html#enable"}),"enabled"),".")),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"cf push console -o splatform/stratos:stable -m 128M -k 384M\n")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: You can replace ",Object(r.b)("inlineCode",{parentName:"p"},"console")," in the command above with a name of your choice for the application")),Object(r.b)("p",null,"Alternatively cf push using a manifest"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"download ",Object(r.b)("a",Object(o.a)({parentName:"li"},{href:"../../../manifest-docker.yml"}),"manifest-docker.yml")," or create your own manifest file:",Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",Object(o.a)({parentName:"pre"},{className:"language-yaml"}),"applications:\n- name: console\n docker:\n image: splatform/stratos:stable\n instances: 1\n memory: 128M\n disk_quota: 384M\n"))),Object(r.b)("li",{parentName:"ul"},"now, you can simply push it to Cloud Foundry:",Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"cf push -f manifest-docker.yml\n")))),Object(r.b)("h2",{id:"associate-cloud-foundry-database-service"},"Associate Cloud Foundry database service"),Object(r.b)("p",null,"Follow instructions ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"db-migration"}),"here"),"."),Object(r.b)("h2",{id:"use-sso-login"},"Use SSO Login"),Object(r.b)("p",null,"By default Stratos will present its own login UI and only supports username and password authentication with your UAA. You can configure Stratos to use UAA's login UI by specifying the the ",Object(r.b)("inlineCode",{parentName:"p"},"SSO_LOGIN")," environment variable in the manifest, for example:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"applications:\n- name: console\n ... memory, disk settings here\n env:\n SSO_LOGIN: true\n")),Object(r.b)("p",null,"When SSO Login is enabled, Stratos will also auto-connect to the Cloud Foundry it is deployed in using the token obtained during the SSO Login flow."),Object(r.b)("p",null,"For more information - see ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"../guides/admin/sso"}),"Single-Sign On"),"."),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),'[\n {\n "destination":"0.0.0.0-255.255.255.255",\n "protocol":"all"\n }\n]\n')),Object(r.b)("p",null,"Save this to a file, e.g. ",Object(r.b)("inlineCode",{parentName:"p"},"my-asg.json"),"."),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: this allows example all network traffic on all IP ranges - we don't recommend using this.")),Object(r.b)("p",null,"Unbind the existing ASG for you organization (",Object(r.b)("inlineCode",{parentName:"p"},"ORG"),") and space (",Object(r.b)("inlineCode",{parentName:"p"},"SPACE"),") with:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"cf unbind-security-group public_networks ORG SPACE\n")),Object(r.b)("p",null,"Create a new ASG using the definition you saved to a file and give it a name, with:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"cf create-security-group NAME my-asg.json\n")),Object(r.b)("p",null,"Bind this ASG to your ",Object(r.b)("inlineCode",{parentName:"p"},"ORG")," and ",Object(r.b)("inlineCode",{parentName:"p"},"SPACE")," with:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"cf bind-security-group NAME ORG SPACE\n")),Object(r.b)("h3",{id:"console-fails-to-start"},"Console fails to start"),Object(r.b)("p",null,"The Stratos Console will automatically detect the API endpoint for your Cloud Foundry. To do so, it relies on the ",Object(r.b)("inlineCode",{parentName:"p"},"cf_api")," value inside the ",Object(r.b)("inlineCode",{parentName:"p"},"VCAP_APPLICATION")," environment variable.\nTo check if the variable is present, use the CF CLI to list environment variables, and inspect the ",Object(r.b)("inlineCode",{parentName:"p"},"VCAP_APPLICATION")," variable under ",Object(r.b)("inlineCode",{parentName:"p"},"System-Provided"),"."),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),'$ cf env console\nGetting env variables for app console in org SUSE / space dev as admin...\nOK\n\nSystem-Provided:\n\n\n {\n "VCAP_APPLICATION": {\n "application_id": ...,\n "application_name": "console",\n "application_uris": ...\n "application_version": ...,\n "cf_api": "http://api.cf-dev.io",\n ...\n }\n\n No user-defined env variables have been set\n ...\n')),Object(r.b)("p",null,"If the ",Object(r.b)("inlineCode",{parentName:"p"},"cf_api")," environment variable is absent then set the ",Object(r.b)("inlineCode",{parentName:"p"},"CF_API_URL")," variable. See the following ",Object(r.b)("em",{parentName:"p"},"Setting the ",Object(r.b)("inlineCode",{parentName:"em"},"CF_API_URL")," env variable in the manifest")," section."),Object(r.b)("p",null,"However, if the ",Object(r.b)("inlineCode",{parentName:"p"},"cf_api")," environment variable is present, and an HTTP address is specified, it is possible that insecure traffic may be blocked. See the following ",Object(r.b)("em",{parentName:"p"},"Setting the ",Object(r.b)("inlineCode",{parentName:"em"},"CF_API_FORCE_SECURE")," env variable in the manifest")," section."),Object(r.b)("h4",{id:"setting-the-cf_api_url-env-variable-in-the-manifest"},"Setting the ",Object(r.b)("inlineCode",{parentName:"h4"},"CF_API_URL")," env variable in the manifest"),Object(r.b)("p",null,"To specify the Cloud Foundry API endpoint, add the ",Object(r.b)("inlineCode",{parentName:"p"},"CF_API_URL")," variable to the manifest, for example:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"applications:\n- name: console\n memory: 256M\n disk_quota: 256M\n host: console\n timeout: 180\n buildpack: https://github.com/cloudfoundry/stratos-buildpack\n health-check-type: port\n env:\n CF_API_URL: https://<>>\n")),Object(r.b)("h4",{id:"setting-the-cf_api_force_secure-env-variable-in-the-manifest"},"Setting the ",Object(r.b)("inlineCode",{parentName:"h4"},"CF_API_FORCE_SECURE")," env variable in the manifest"),Object(r.b)("p",null,"To force the console to use secured communication with the Cloud Foundry API endpoint (HTTPS rather than HTTP), specify the ",Object(r.b)("inlineCode",{parentName:"p"},"CF_API_FORCE_SECURE")," environment in the manifest, for example:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"applications:\n- name: console\n memory: 256M\n disk_quota: 256M\n host: console\n timeout: 180\n buildpack: https://github.com/cloudfoundry/stratos-buildpack\n health-check-type: port\n env:\n CF_API_FORCE_SECURE: true\n")))}b.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return p})),n.d(t,"b",(function(){return m}));var o=n(0),a=n.n(o);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function l(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=a.a.createContext({}),b=function(e){var t=a.a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=b(e.components);return a.a.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},d=a.a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,i=e.parentName,s=c(e,["components","mdxType","originalType","parentName"]),p=b(n),d=o,m=p["".concat(i,".").concat(d)]||p[d]||u[d]||r;return n?a.a.createElement(m,l(l({ref:t},s),{},{components:n})):a.a.createElement(m,l({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,i=new Array(r);i[0]=d;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var s=2;s=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var d=r.a.createContext({}),s=function(e){var t=r.a.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=s(e.components);return r.a.createElement(d.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},b=r.a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,a=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),u=s(n),b=o,O=u["".concat(a,".").concat(b)]||u[b]||p[b]||c;return n?r.a.createElement(O,i(i({ref:t},d),{},{components:n})):r.a.createElement(O,i({ref:t},d))}));function O(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=n.length,a=new Array(c);a[0]=b;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var d=2;d=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var d=o.a.createContext({}),p=function(e){var t=o.a.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},u=function(e){var t=p(e.components);return o.a.createElement(d.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},s=o.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,i=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),u=p(n),s=r,m=u["".concat(i,".").concat(s)]||u[s]||b[s]||a;return n?o.a.createElement(m,c(c({ref:t},d),{},{components:n})):o.a.createElement(m,c({ref:t},d))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=s;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c.mdxType="string"==typeof e?e:r,i[1]=c;for(var d=2;d=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=o.a.createContext({}),s=function(e){var t=o.a.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},d=function(e){var t=s(e.components);return o.a.createElement(u.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},p=o.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,i=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=s(n),p=r,h=d["".concat(i,".").concat(p)]||d[p]||b[p]||a;return n?o.a.createElement(h,c(c({ref:t},u),{},{components:n})):o.a.createElement(h,c({ref:t},u))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=p;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c.mdxType="string"==typeof e?e:r,i[1]=c;for(var u=2;u=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=o.a.createContext({}),s=function(e){var t=o.a.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=s(e.components);return o.a.createElement(u.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},d=o.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,i=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),p=s(n),d=r,m=p["".concat(i,".").concat(d)]||p[d]||b[d]||a;return n?o.a.createElement(m,l(l({ref:t},u),{},{components:n})):o.a.createElement(m,l({ref:t},u))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=d;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:r,i[1]=l;for(var u=2;u=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var p=o.a.createContext({}),l=function(e){var n=o.a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},f=function(e){var n=l(e.components);return o.a.createElement(p.Provider,{value:n},e.children)},s={inlineCode:"code",wrapper:function(e){var n=e.children;return o.a.createElement(o.a.Fragment,{},n)}},d=o.a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,a=e.parentName,p=u(e,["components","mdxType","originalType","parentName"]),f=l(t),d=r,b=f["".concat(a,".").concat(d)]||f[d]||s[d]||i;return t?o.a.createElement(b,c(c({ref:n},p),{},{components:t})):o.a.createElement(b,c({ref:n},p))}));function b(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,a=new Array(i);a[0]=d;var c={};for(var u in n)hasOwnProperty.call(n,u)&&(c[u]=n[u]);c.originalType=e,c.mdxType="string"==typeof e?e:r,a[1]=c;for(var p=2;p\nSMTP_HOST=127.0.0.1\nSMTP_PASSWORD=\nSMTP_PORT=1025\nSMTP_USER=\nTEMPLATE_DIR=./templates\n")))}s.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return u})),n.d(t,"b",(function(){return m}));var a=n(0),r=n.n(a);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var b=r.a.createContext({}),s=function(e){var t=r.a.useContext(b),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},u=function(e){var t=s(e.components);return r.a.createElement(b.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},d=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,b=c(e,["components","mdxType","originalType","parentName"]),u=s(n),d=a,m=u["".concat(l,".").concat(d)]||u[d]||p[d]||i;return n?r.a.createElement(m,o(o({ref:t},b),{},{components:n})):r.a.createElement(m,o({ref:t},b))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,l=new Array(i);l[0]=d;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var b=2;b\n skipSSLValidation: true\n testOrg: e2e\n testSpace: e2e\n testService: app-autoscaler\n services:\n bindApp: go-env\n publicService:\n name: public-service\n privateService:\n name: private-service\n invalidOrgName: test-e2e\n invalidSpaceName: test-e2e\n spaceScopedService:\n name: space-scoped-service\n invalidOrgName: test-e2e\n invalidSpaceName: test-e2e\n creds:\n admin:\n username: \n password: \n nonAdmin:\n username: e2e\n password: changeme\n removeUser:\n username: e2e-remove-user\n password: changeme\n invite:\n clientId: stratos-invite\n clientSecret: changeme\n uaa:\n creds:\n clientId: \n clientSecret: \n tokenEndpoint: \n zone: \n")),Object(i.b)("h3",{id:"tidying-up-test-generated-cf-entities"},"Tidying up test generated CF entities"),Object(i.b)("p",null,"If tests are stopped before completing or fail to clean old test artifacts will exist in the CF. To clean some of these please see the script\nat ",Object(i.b)("a",Object(r.a)({parentName:"p"},{href:"../deploy/ci/automation/e2e-clean-remnants.sh"}),"deploy/ci/automation/e2e-clean-remnants.sh")),Object(i.b)("h2",{id:"running-the-tests"},"Running the tests"),Object(i.b)("p",null,"To run the tests against an instance of Stratos execute"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{}),"npm run e2e -- --dev-server-target= --base-url==0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=a.a.createContext({}),b=function(e){var t=a.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},u=function(e){var t=b(e.components);return a.a.createElement(l.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},d=a.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,s=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),u=b(n),d=r,m=u["".concat(s,".").concat(d)]||u[d]||p[d]||i;return n?a.a.createElement(m,o(o({ref:t},l),{},{components:n})):a.a.createElement(m,o({ref:t},l))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,s=new Array(i);s[0]=d;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:r,s[1]=o;for(var l=2;l.bluemix.net")," avoids a proxy, ",Object(a.b)("inlineCode",{parentName:"p"},"https://mccp..bluemix.net"),",\nthat IBM tools use to flesh out users with their username. This results in a missing ",Object(a.b)("inlineCode",{parentName:"p"},"username")," field, which we fill with the user's ",Object(a.b)("inlineCode",{parentName:"p"},"guid"),"\ninstead. "),Object(a.b)("h3",{id:"solution"},"Solution"),Object(a.b)("p",null,"Unregister the IBM Cloud endpoint that contains the address ",Object(a.b)("inlineCode",{parentName:"p"},"https://api..bluemix.net")," and register again with the address\n",Object(a.b)("inlineCode",{parentName:"p"},"https://mccp..bluemix.net")))}s.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return p})),n.d(t,"b",(function(){return m}));var r=n(0),o=n.n(r);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=o.a.createContext({}),s=function(e){var t=o.a.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p=function(e){var t=s(e.components);return o.a.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},b=o.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,i=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),p=s(n),b=r,m=p["".concat(i,".").concat(b)]||p[b]||d[b]||a;return n?o.a.createElement(m,c(c({ref:t},u),{},{components:n})):o.a.createElement(m,c({ref:t},u))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=b;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c.mdxType="string"==typeof e?e:r,i[1]=c;for(var u=2;u bosh_ca_cert\n")),Object(i.b)("p",null,"Get the BOSH URL by examining your config file:"),Object(i.b)("pre",null,Object(i.b)("code",Object(o.a)({parentName:"pre"},{}),"cat ~/.bosh/config\n")),Object(i.b)("p",null,"Find the ",Object(i.b)("inlineCode",{parentName:"p"},"vbox")," environment and make a note of the url field - set an environment variable ",Object(i.b)("inlineCode",{parentName:"p"},"BOSH_IP")," to this value."),Object(i.b)("p",null,"You can now deploy Prometheus Bosh Release with:"),Object(i.b)("pre",null,Object(i.b)("code",Object(o.a)({parentName:"pre"},{}),"bosh -d prometheus deploy manifests/prometheus.yml \\\n --vars-store tmp/deployment-vars.yml \\\n -o manifests/operators/monitor-bosh.yml \\\n -v metrics_environment=doppler.local.pcfdev.io:443 \\\n -o manifests/operators/monitor-cf.yml \\\n -v system_domain=local.pcfdev.io \\\n -v metron_deployment_name=local.pcfdev.io \\\n -v uaa_clients_cf_exporter_secret=prometheus-client-secret \\\n -v uaa_clients_firehose_exporter_secret=prometheus-client-secret \\\n -v traffic_controller_external_port=443 \\\n -v skip_ssl_verify=true \\\n -v bosh_password=${BOSH_CLIENT_SECRET} \\\n -v bosh_username=${BOSH_CLIENT} \\\n -v bosh_url=https://${BOSH_IP}:25555 \\\n --var-file bosh_ca_cert=bosh_ca_cert\n")),Object(i.b)("p",null,"Wait for deployment to complete."),Object(i.b)("p",null,"List the instances in the deployment with:"),Object(i.b)("pre",null,Object(i.b)("code",Object(o.a)({parentName:"pre"},{}),"bosh instances -d prometheus\n")),Object(i.b)("p",null,"Find the IP Address for the ",Object(i.b)("inlineCode",{parentName:"p"},"prometheus2")," instance. The Prometheus endpoint will be: ",Object(i.b)("inlineCode",{parentName:"p"},"http://IP:9090"),"."),Object(i.b)("p",null,"Open a web browser and load the Prometheus URL. open the ",Object(i.b)("inlineCode",{parentName:"p"},"Status")," menu and select targets. Refresh the page until the firehose target is up."),Object(i.b)("blockquote",null,Object(i.b)("p",{parentName:"blockquote"},"Note: It can take a few minutes before all of the targets appear in Prometheus and their state becomes ",Object(i.b)("inlineCode",{parentName:"p"},"UP"),". You should see targets named ",Object(i.b)("inlineCode",{parentName:"p"},"bosh"),", ",Object(i.b)("inlineCode",{parentName:"p"},"cf")," and ",Object(i.b)("inlineCode",{parentName:"p"},"firehose")," as well as many others if everything is working correctly.")),Object(i.b)("p",null,"You should now be able to follow the ",Object(i.b)("a",Object(o.a)({parentName:"p"},{href:"#connecting-prometheus-to-stratos"}),"Connecting Prometheus to Stratos")," instructions for registering and connecting Prometheus to Stratos."))}p.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return b})),n.d(t,"b",(function(){return m}));var o=n(0),r=n.n(o);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function s(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=r.a.createContext({}),p=function(e){var t=r.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},b=function(e){var t=p(e.components);return r.a.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},h=r.a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,a=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),b=p(n),h=o,m=b["".concat(a,".").concat(h)]||b[h]||u[h]||i;return n?r.a.createElement(m,s(s({ref:t},l),{},{components:n})):r.a.createElement(m,s({ref:t},l))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=h;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:o,a[1]=s;for(var l=2;l=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var d=a.a.createContext({}),s=function(e){var t=a.a.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=s(e.components);return a.a.createElement(d.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},u=a.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,o=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),p=s(n),u=r,m=p["".concat(o,".").concat(u)]||p[u]||b[u]||i;return n?a.a.createElement(m,l(l({ref:t},d),{},{components:n})):a.a.createElement(m,l({ref:t},d))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,o=new Array(i);o[0]=u;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:r,o[1]=l;for(var d=2;d0&&m.a.createElement("section",{className:d.a.features},m.a.createElement("div",{className:"container"},m.a.createElement("div",{className:"row"},g.map((e,a)=>m.a.createElement(p,Object(n.a)({key:a},e)))))),m.a.createElement("section",{className:Object(o.a)(d.a.features,"screenshot-section","blue")},m.a.createElement("div",{className:"container"},m.a.createElement("div",{class:"screenshot"},m.a.createElement("img",{class:"left",src:"img/screens/cf-app.png"}),m.a.createElement("div",null,m.a.createElement("h2",null,"Cloud Foundry"),m.a.createElement("p",null,"Deploy and manage applications in Cloud Foundry. Stream application logs, scale applications and ssh to application instances"),m.a.createElement("p",null,"View and manage Cloud Foundry organizations and spaces and quotas."),m.a.createElement("p",null,"Browse the Service Marketplace and create and manage service instances."),m.a.createElement("p",null,"and a whole lot more ..."))))),m.a.createElement("section",{className:Object(o.a)(d.a.features,"screenshot-section","white")},m.a.createElement("div",{className:"container"},m.a.createElement("div",{class:"screenshot"},m.a.createElement("div",null,m.a.createElement("h2",null,"Kubernetes"),m.a.createElement("p",null,"View cluster-level metadata"),m.a.createElement("p",null,"Browse, view and install Helm Charts"),m.a.createElement("p",null,"View Helm Releases and see relationships between Kubernetes Resources"),m.a.createElement("p",null,"and lots more ...")),m.a.createElement("img",{class:"right",src:"img/screens/kube-graph.png"})))),m.a.createElement("section",{className:Object(o.a)(d.a.features,"screenshot-section","blue")},m.a.createElement("div",{className:"container"},m.a.createElement("div",{class:"screenshot"},m.a.createElement("img",{class:"left",src:"img/screens/endpoints.png"}),m.a.createElement("div",null,m.a.createElement("h2",null,"Multi-Cluster"),m.a.createElement("p",null,"Add and Connect multiple Cloud Foundry and/or Kubernetes clusters."),m.a.createElement("p",null,"Seemlessly switch between clusters and get aggregated views across clusters."),m.a.createElement("p",null,"Favorite clusters and entities for easy access from the Home screen.")))))))}}}]); \ No newline at end of file diff --git a/website/site-dist/c925d2ad.68228bc6.js b/website/site-dist/c925d2ad.68228bc6.js new file mode 100644 index 0000000000..f37023521b --- /dev/null +++ b/website/site-dist/c925d2ad.68228bc6.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{137:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return a})),n.d(t,"metadata",(function(){return c})),n.d(t,"rightToc",(function(){return s})),n.d(t,"default",(function(){return p}));var r=n(2),o=n(6),i=(n(0),n(149)),a={title:"Theming Stratos",sidebar_label:"Theming Stratos"},c={id:"extensions/theming",isDocsHomePage:!1,title:"Theming Stratos",description:"This document is in progress",source:"@site/docs/extensions/theming.md",permalink:"/docs/extensions/theming",editUrl:"https://github.com/cloudfoundry/stratos/edit/master/website/docs/extensions/theming.md",sidebar_label:"Theming Stratos",sidebar:"docs",previous:{title:"Customizing Stratos",permalink:"/docs/guides/customization/customizing"},next:{title:"Frontend Extensions",permalink:"/docs/extensions/frontend"}},s=[],u={rightToc:s};function p(e){var t=e.components,n=Object(o.a)(e,["components"]);return Object(i.b)("wrapper",Object(r.a)({},u,n,{components:t,mdxType:"MDXLayout"}),Object(i.b)("p",null,"This document is in progress"))}p.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return l})),n.d(t,"b",(function(){return d}));var r=n(0),o=n.n(r);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=o.a.createContext({}),p=function(e){var t=o.a.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},l=function(e){var t=p(e.components);return o.a.createElement(u.Provider,{value:t},e.children)},f={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},m=o.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,a=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),l=p(n),m=r,d=l["".concat(a,".").concat(m)]||l[m]||f[m]||i;return n?o.a.createElement(d,c(c({ref:t},u),{},{components:n})):o.a.createElement(d,c({ref:t},u))}));function d(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,a=new Array(i);a[0]=m;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:r,a[1]=c;for(var u=2;u=0||(c[n]=e[n]);return c}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(c[n]=e[n])}return c}var s=c.a.createContext({}),u=function(e){var t=c.a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},b=function(e){var t=u(e.components);return c.a.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return c.a.createElement(c.a.Fragment,{},t)}},d=c.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,r=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),b=u(n),d=a,m=b["".concat(r,".").concat(d)]||b[d]||p[d]||i;return n?c.a.createElement(m,o(o({ref:t},s),{},{components:n})):c.a.createElement(m,o({ref:t},s))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,r=new Array(i);r[0]=d;var o={};for(var l in t)hasOwnProperty.call(t,l)&&(o[l]=t[l]);o.originalType=e,o.mdxType="string"==typeof e?e:a,r[1]=o;for(var s=2;s + + + + + +LICENSE | STRATOS + + + + + + + + + + + + +
+

LICENSE

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

  1. Definitions.

    "License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document.

    "Licensor" shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License.

    "Legal Entity" shall mean the union of the acting entity and all +other entities that control, are controlled by, or are under common +control with that entity. For the purposes of this definition, +"control" means (i) the power, direct or indirect, to cause the +direction or management of such entity, whether by contract or +otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity.

    "You" (or "Your") shall mean an individual or Legal Entity +exercising permissions granted by this License.

    "Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation +source, and configuration files.

    "Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types.

    "Work" shall mean the work of authorship, whether in Source or +Object form, made available under the License, as indicated by a +copyright notice that is included in or attached to the work +(an example is provided in the Appendix below).

    "Derivative Works" shall mean any work, whether in Source or Object +form, that is based on (or derived from) the Work and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. For the purposes +of this License, Derivative Works shall not include works that remain +separable from, or merely link (or bind by name) to the interfaces of, +the Work and Derivative Works thereof.

    "Contribution" shall mean any work of authorship, including +the original version of the Work and any modifications or additions +to that Work or Derivative Works thereof, that is intentionally +submitted to Licensor for inclusion in the Work by the copyright owner +or by an individual or Legal Entity authorized to submit on behalf of +the copyright owner. For the purposes of this definition, "submitted" +means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, +and issue tracking systems that are managed by, or on behalf of, the +Licensor for the purpose of discussing and improving the Work, but +excluding communication that is conspicuously marked or otherwise +designated in writing by the copyright owner as "Not a Contribution."

    "Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work.

  2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form.

  3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work, +where such license applies only to those patent claims licensable +by such Contributor that are necessarily infringed by their +Contribution(s) alone or by combination of their Contribution(s) +with the Work to which such Contribution(s) was submitted. If You +institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work +or a Contribution incorporated within the Work constitutes direct +or contributory patent infringement, then any patent licenses +granted to You under this License for that Work shall terminate +as of the date such litigation is filed.

  4. Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You +meet the following conditions:

    (a) You must give any other recipients of the Work or +Derivative Works a copy of this License; and

    (b) You must cause any modified files to carry prominent notices +stating that You changed the files; and

    (c) You must retain, in the Source form of any Derivative Works +that You distribute, all copyright, patent, trademark, and +attribution notices from the Source form of the Work, +excluding those notices that do not pertain to any part of +the Derivative Works; and

    (d) If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must +include a readable copy of the attribution notices contained +within such NOTICE file, excluding those notices that do not +pertain to any part of the Derivative Works, in at least one +of the following places: within a NOTICE text file distributed +as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, +within a display generated by the Derivative Works, if and +wherever such third-party notices normally appear. The contents +of the NOTICE file are for informational purposes only and +do not modify the License. You may add Your own attribution +notices within Derivative Works that You distribute, alongside +or as an addendum to the NOTICE text from the Work, provided +that such additional attribution notices cannot be construed +as modifying the License.

    You may add Your own copyright statement to Your modifications and +may provide additional or different license terms and conditions +for use, reproduction, or distribution of Your modifications, or +for any such Derivative Works as a whole, provided Your use, +reproduction, and distribution of the Work otherwise complies with +the conditions stated in this License.

  5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions.

  6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file.

  7. Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License.

  8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages.

  9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/advanced/invite-user-guide/index.html b/website/site-dist/docs/advanced/invite-user-guide/index.html new file mode 100644 index 0000000000..defb0f67ac --- /dev/null +++ b/website/site-dist/docs/advanced/invite-user-guide/index.html @@ -0,0 +1,35 @@ + + + + + + +Configuring Invite User Support | STRATOS + + + + + + + + + + + + +
+

Configuring Invite User Support

Stratos provides a way for Cloud Foundry administrators and organization managers to invite users to an organization or space.

During the invite process the following actions will occur:

  • A UAA user and a CF user will be created.
  • Initial roles will be assigned. User will be added as an organization member and, if selected, a space role.
  • Users will be emailed a verification link. The link directs the user to a UAA site to set their password.

Note - The user will not be able to log in without first setting their password but CF admins, organization managers and space managers will be able to set roles for the user.

Set up

In order to enable User Invite support in Stratos:

  1. A UAA client must be created with appropriate permissions to create users
  2. Stratos must be configured with the details of the SMTP server to use when sending emails
  3. (Optionally) The email templates used for sending emails should be modified
  4. User Invite support must be enabled in Stratos by an Administrator

Once all of the steps have been completed, CF administrators and organization managers will be able to invite users via the Organization and Space pages under the 'Users' tab.

These steps are covered below.

Creating a UAA Client for User Invites

Stratos requires a pre-configured UAA client to invite the UAA user and create the CF user. The client requires both the scim.invite and cloud_controller.admin scopes.

To create a client with the correct scopes, use the following UAA CLI command:

uaac client add stratos-invite --scope scim.invite,cloud_controller.admin --authorized_grant_types client_credentials --authorities scim.invite,cloud_controller.admin -s password

Note - Include the uaa scope if required.

In the above example the client id is stratos-invite and client secret is password.

Alternatively, you can use an existing UAA Client, if one is already available with the appropriate scopes.

Note: You will need the Client ID and Client Secret used above when enabling User Invite support in the Stratos UI

Configuring SMTP Server details and (optionally) modifying Email Templates

Configuration depends on how you have deployed Stratos.

  1. For cf push, see Configuration for CF Push
  2. For Kubernetes with Helm, see: Configuration for Helm Installation

Enabling User Invite support in Stratos

This action must be performed by an Administrator in Stratos.

1) Navigate to the Cloud Foundry Summary page of the required CF. +1) Use the Configure button in the User Invitation Support section. +1) Supply the uaa client id and secret and click Configure

Note: If Stratos has been deployed via cf push and the steps under the Pre-configure invite UAA client header in the CF deploy guide have been followed, you will not follow these steps for the default CF.

Configuration for CF Push

When deploying Stratos to Cloud Foundry using cf push, User Invites can be configured as follows.

General Configuration

The following configuration is required in order to configure the SMTP server and email subject:

Environment VariablePurpose
SMTP_HOSTHost name of the SMTP server
SMTP_PORTPort name of the SMTP server
SMTP_AUTHWhether to authenticate against the SMTP server using AUTH command (set to "true")
SMTP_FROM_ADDRESSFrom email address to use when sending emails
SMTP_USERUsername to use when authenticating with the email server
SMTP_PASSWORDPassword to use when authenticating with the email server
INVITE_USER_SUBJECTSubject line to use when sending an invitation email

Using custom templates

To use custom email templates, create a folder and add the two templates with the following file names:

  1. user-invite-email.txt = Plain text template
  2. user-invite-email.helm = HTML text template

When deploying Stratos with cf push set the environment variable TEMPLATE_DIR to the folder name where your custom templates are located. This can be done on the command line or by adding this environment variable to the manifest.yml file.

Configuration for Helm Installation

When deploying Stratos to Kubernetes using Helm, User Invites can be configured as follows.

General Configuration

The following configuration is required in order to configure the SMTP server and email subject:

Helm Chart ValuePurpose
env.SMTP_HOSTHost name of the SMTP server
env.SMTP_PORTPort name of the SMTP server
env.SMTP_AUTHWhether to authenticate against the SMTP server using AUTH command (set to "true")
env.SMTP_FROM_ADDRESSFrom email address to use when sending emails
env.SMTP_USERUsername to use when authenticating with the email server
env.SMTP_PASSWORDPassword to use when authenticating with the email server
console.userInviteSubjectSubject line to use when sending an invitation email

Using custom templates

If you wish to use custom email templates for user invitation, follow these steps:

Create the namespace that you are going to use when installing Stratos:

kubectl create namespace stratos

Create a Config Map for the template files - this assumes you have the following two files in the current directory:

  1. user-invite-email.txt = Plain text template
  2. user-invite-email.helm = HTML text template

Create the Config Map with:

kubectl create configmap stratos-templates --namespace stratos --from-file=./user-invite-email.txt --from-file=./user-invite-email.html

When deploying Stratos using Helm, ensure you set the the Helm Value:

console.templatesConfigMapName

to the name of the Config Map that you created - e.g. in the example above, add the following to the helm install command:

--set console.templatesConfigMapName=stratos-templates

Development Notes

When developing locally, we recommend using mailcatcher in place of an actual SMTP server.

To install mailcatcher via docker, use the following command: docker run -d -p 1080:80 -p 1025:25 --name mail tophfr/mailcatcher. Once mailcatcher is installed, continue to follow the instructions below.

SMTP server details can be set via rhe usual environment variable approach or, when running locally, in the jetstream/config.properties file (see Backend Development - Configuration in developers-guide). The config settings, with example values, are as follows:

SMTP_FROM_ADDRESS=Stratos<test@test.com>
SMTP_HOST=127.0.0.1
SMTP_PASSWORD=
SMTP_PORT=1025
SMTP_USER=
TEMPLATE_DIR=./templates
+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/advanced/sso/index.html b/website/site-dist/docs/advanced/sso/index.html new file mode 100644 index 0000000000..b87c674c03 --- /dev/null +++ b/website/site-dist/docs/advanced/sso/index.html @@ -0,0 +1,35 @@ + + + + + + +Configuring Single Sign On | STRATOS + + + + + + + + + + + + +
+

Configuring Single Sign On

By default, Stratos will authenticate against a UAA using username and password, for both logging into Stratos and when connecting Cloud Foundry endpoints.

UAA can support richer login mechanisms than username and password. To accommodate this, you can configure Stratos to use the UAA's Single Sign On UI for login.

This can be enabled by setting the config setting SSO_LOGIN to true.

Most importantly, you will need to ensure that the Client used when communicating with your UAA is configured to allow Stratos to use Single Sign On - i.e. that the Stratos SSO Login callback URI is registered with the UAA.

Adding the Stratos SSO Callback URI

You'll need the uaac CLI to configure your Client to accept the Stratos SSO Callback URI - see here.

NOTE: The Stratos SSO Redirect URI that you'll need is: +https://HOST.DOMAIN/pp/v1/auth/sso_login_callback +where HOST and DOMAIN depend on your Stratos installation.

Target your UAA

uaac target <UAA URL>

Login to your UAA with the admin client:

uaac token client get admin -s <ADMIN_CLIENT_SECRET>

Next, check the configuration of your Client - for example, for the cf client:

uaac client get cf

You'll get the current configuration - there are two properties of interest redirect_uri and authorized_grant_types.

Note: The following commands will overwrite existing values for the settings specified. To keep the existing values along with the new value include them in the new value as a comma-separated list.

The redirect_uri value should contain the Stratos redirect URI. If not update the Client with:

uaac client update cf --redirect_uri https://HOST.DOMAIN/pp/v1/auth/sso_login_callback

The authorized_grant_types value should contain authorization_code. If not update the Client with:

uaac client update cf --authorized_grant_types authorization_code

Adding a Stratos SSO State Whitelist

When SSO has been configured Stratos's log in request will contain a URL that tells SSO where to return to. When using a browser this is automatically populated. To avoid situations where this can be hijacked or called separately an SSO state whitelist can be provided via the environment variable SSO_WHITELIST. This is a comma separated list. For example...

SSO_WHITELIST=https://your.domain/*
SSO_WHITELIST=https://your.domain/*,https://your.other.domain/*

When set, any requests to log in with a different state will be denied.

In order for the SSO state to match an entry from the whitelist the schema, hostname, port and path must match exactly. A wildcard * can be provided for the path to match anything.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/cf-api-v2-usage/index.html b/website/site-dist/docs/cf-api-v2-usage/index.html new file mode 100644 index 0000000000..57ee4d8dda --- /dev/null +++ b/website/site-dist/docs/cf-api-v2-usage/index.html @@ -0,0 +1,62 @@ + + + + + + +cf-api-v2-usage | STRATOS + + + + + + + + + + + + +
+

cf-api-v2-usage

Cloud Foundry API v2 Feature Usage

  1. High Level Stratos Concepts
  2. API Parameters
  3. API Examples
  4. V2 Specifics
  5. V2 Summary

High Level Stratos Concepts

Stratos exercises many features of the Cloud Foundry v2 API, in order to understand these a general knowledge of Stratos concepts is required

Lists

  • Collections of entities are presenting using a list component, which covers table and card grid views.
  • Lists can be
    • Sorted by a number of fields
    • Filtered by text or Cloud Foundry, Organisation or Space (some lists contain entities from multiple cloud foundries)
    • Paginated
  • Example 1 - Applications List
    • Applications sorting by application name, instances, disk quota, memory and creation date
    • Applications filtered by name, cf, organisation or space
  • Example 2 - Organisation List
    • Orgs sorted by name or creation date
    • Orgs filtered by name
  • In order to support a decent level of filtering and sorting we often fetch all entities and store them locally (these are referred to as local lists)
  • Alternatively, in places where we don't need as much rich filtering and sorting, or the amount of entities are too high, we use standard +page requests and whatever sorting and filtering is available (these are referred to as non-local lists)

Entity Relations & Validation

  • Cloud Foundry entities (organisation, route, service plan, etc) are stored client side in an entity store
  • The console provides methods to fetch an entity or collection of entities from the store. At this time Stratos states if any of the +entity's relations are required, for instance when fetching an organisation the spaces and services properties may be required
  • The console checks if the required entity/s exist in the store.
    • If they're missing they're then fetched via the API, including any required relationships
    • If they exist in the store their relations are checked. Any missing relations are fetched using the <relation name>_url property
  • This means we fetch the minimum amount of data, and can ensure we have the required data when it's needed
  • If the relationship is one to many then all of the missing entities are fetched, even if this involved more than one request.
  • Example 1
    • To filter the applications in the applications list by cf/org/space we fetch a list of organisations and state each org must have it's +spaces property
      • The resulting org entity will only have the space's relation, each space will have no other relation
    • The user navigates to a space summary screen
    • The space summary screen states the space should contain applications, service instances, space quota, service binding, etc
    • Entity validation will fetch the missing relations using the _url of the relation
  • Examples 2
    • To show the applications in the applications list we fetch a list of apps with the following relations
      • application - space
      • space - organisation
      • application - route
    • The user navigates to a application summary screen
    • The application summary screen states the application should have
      • application - route
      • application - space
      • application - stack
      • application - service binding
      • route - domain
      • space - organisation
    • Entity validation will then usually* fetch the two missing entities stack and domain
      • Depending on what entities currently exist in the store having been fetched by other calls

Summary Stats

  • Some pages show summary information to do with an entity (Application, Organisation, Service, etc)
  • Some of these will show stats where only the count of entities are required
  • Example 1 - Service Summary
    • No# of service instances
    • No# of service plans
  • Example 2 - Organisation Summary
    • No# of spaces in organisation
    • No# of applications in organisation
    • No# of application instances in organisation
    • No# of User in organisation
    • Memory usage (total memory of running apps) out of organisation memory quota
    • Routes in organisation out of organisation root quota
    • Private domains out of organisation private domain quota
    • Service instance count out of organisation instance quota

Application State

  • In most places where we present an application we show a summary state
  • Examples
    • Pending
    • Offline while Updating
    • Deployed - No Instances
    • Deployed - Scaling App
    • Deployed - Crashing
  • Summary state is a combination of
    • App state
    • App package_state
    • App package_updated_at
    • App instances
    • App Stats instances collection
  • To present these kind of states we need to call the /stats endpoint for each app. This means on the Applications list we cannot sort by +app state (there could be thousands of apps).

Users, Roles and Permissions

The console user will connect to a CF with their personal CF credentials. These credentials dictate not only what they're allowed to do in +the console but also how we have to fetch data.

Listing users & their roles

  • We provide a way for users of all types to view a list of users (at the cf, organisation and space levels) and their roles
  • We have to fetch this information differently between CF administrators with certain scopes and non-cf administrators
  • CF Admins can list users via /users
  • Non-CF admins cannot access /users list (aside from themselves)
    • At the CF level we do not show a list of all users
    • At the org level we show all users via organizations/${guid}/users
    • At the space level we show all users via spaces/${guid}/user_roles

Permissions

  • Permissions are dictated by the admin/non-admin state of the connected user, cf feature flags and all of the users organisation and space roles
  • For CF admins we skip fetching roles, as their admin state overrides roles
  • For non-admins we hit each users/<non-admin's guid>/<role> endpoint, there's a lot of duplicated data (orgs and spaces) here

API Parameters

Relations (include-relations, inline-relations-depth)

In order to support the entity validation process described above we make heavy use of the generic inline-relations-depth and include-relations parameters

Note - exclude-relations is not used.

When we show the Space summary page the following space relations are required

  • space - routes
  • space - quota
  • space - service instances
  • service instance - service bindings
  • service bindings - application
  • space - applications

include-relations

Given the space summary example, on a fresh load of the console directly to a space summary page equates to

include-relations=routes,space_quota_definition,service_instances,service_bindings,app,apps
  • As there's only one way to define the parent in a include-relations string any child relation with the same name in both parent and +child will be fetched. For example if space contained an apps property and one of it's children also had an apps property both will be +fetched.

  • If a relationship contains a list of entities, and that list contains more than 50, the collection is missing in the API response. As per +non-list entities we use the <x>_url value to fetch these, however will automatically fetch all values and not just the first page (just +like a local-list).

inline-relations-depth

The inline depth, up to 2, is calculated by the number of chained relations. In the space summary example above the actual depth is 3 +(space --> service instance --> service binding --> application). As 2 is the maximum the last relation of binding --> application is +missing in the api response. If the missing application is not already in the store it's fetched by the <x>_url value.

Pagination (page, results-per-page)

  • Pagination is either controlled
    • locally (local lists)
      • We fetch all entities by setting results-per-page to maximum and iterate through every page
      • Paging is then handled client side
    • remotely (non-local lists)
      • We fetch pages that haven't been fetched before in a page size determined by the user

Sorting (order-direction)

  • The CF API only supports sorting on a very small subset of properties such as creation_date and event timestamp
  • This is only used when sorting non-local lists (see pagination section above)

Queries (q)

  • We have the functionality to use these per list, however are rarely used
    • The Application Events non-local list uses these to define the actee (the app)
    • The Applications list uses these to filter by org/space when there are too many applications to handle locally
    • Fetch all service instances with a service bindings
    • Fetch all service instances with a service plan
  • Using q to filter via org and space is sometimes possible, sometimes not
    • A route is created in a space, however cannot filter routes via space
    • Service brokers can be filtered by space, however not by organisation

Scaling

We've recently started updating a lot of features to be sensitive of CFs with large collections of entities. This involves...

  • Local Lists will check the total number of results before fetching them all. If too high we refuse to show the table/cards.
  • Counts of entities are done via results-per-page of 1 and total_results instead of fetching all entities
  • Inline relations of one to many, and the count might be too high, are removed and the functionality that requires them reworked
    • For instance space --> routes
    • Some will remain the same, for instance service --> service plans

API Examples

User visits applications lists... and then views an application summary page

Applications List
organizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=1&include-relations=spaces
apps?order-direction=asc&order-direction-field=creation&page=1&results-per-page=100&inline-relations-depth=2&include-relations=space,organization,routes
organizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/fe72bac0-6d22-495c-a1d8-67180461f52f/stats?order-direction=desc&order-direction-field=index&results-per-page=5
Nav to Application Summary
apps/ca47f757-caf7-4142-803b-a577c995869f/env?order-direction=desc&order-direction-field=name&results-per-page=5&page=1
stacks/83eaeaa0-dbd0-4ff9-bb28-50adbbce4e78
shared_domains/a09e5ec7-ddc4-476d-a431-a45af446d2f2
apps/ca47f757-caf7-4142-803b-a577c995869f/service_bindings?results-per-page=100&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f/summary

User directly visits application summary page

Calls
apps/ca47f757-caf7-4142-803b-a577c995869f/env?order-direction=desc&order-direction-field=name&results-per-page=5&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f?inline-relations-depth=2&include-relations=stack,space,organization,routes,domain,service_bindings
apps/ca47f757-caf7-4142-803b-a577c995869f/summary
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1

User sits on application summary view

The following is repeated
apps/ca47f757-caf7-4142-803b-a577c995869f?inline-relations-depth=2&include-relations=stack,space,organization,routes,domain,service_bindings
apps/ca47f757-caf7-4142-803b-a577c995869f/summary
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1

User navigates to space summary view from cf summary view and org summary view

Cf Summary View
shared_domains?results-per-page=100&page=1
organizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps
users?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=1&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1
users/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3
organizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2
organizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1&inline-relations-depth=1&include-relations=routes,service_instances,apps
Nav to Org Summary View
organizations/78ee5f44-0a33-4544-9fa8-acb0de7155ce/users?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1
users/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3
Nav to Space Summary View
service_instances/f2656532-e77c-46fa-a2cb-595e6957e6f6/service_bindings?results-per-page=100&page=1&inline-relations-depth=1&include-relations=app
service_instances/99e91478-b485-469f-a653-a3dd5bc84b4f/service_bindings?results-per-page=100&page=1&inline-relations-depth=2&include-relations=app
service_instances/3db6b84a-71eb-4c16-b9ff-6e71f7981dab/service_bindings?results-per-page=100&page=1&inline-relations-depth=2&include-relations=app
service_instances/b7d411a1-5ab4-4159-a34a-73b9a9b4e733/service_bindings?results-per-page=100&page=1&inline-relations-depth=2&include-relations=app
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/user_roles?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1
users/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3

User directly visits an space summary view

Calls
shared_domains?results-per-page=100&page=1
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9?inline-relations-depth=2&include-relations=routes,space_quota_definition,service_instances,service_bindings,app,apps
organizations/78ee5f44-0a33-4544-9fa8-acb0de7155ce?inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/user_roles?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=1&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces
organizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps
users?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1
users/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1
users/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3
organizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps
organizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1&inline-relations-depth=1&include-relations=routes,service_instances,apps
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5

Random click around (fetching data)

This shows a whole range of calls we make, all `GET`s
organizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=1&include-relations=spaces
apps?order-direction=asc&order-direction-field=creation&page=1&results-per-page=100&inline-relations-depth=2&include-relations=space,organization,routes
organizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=1&include-relations=spaces
organizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1
apps?order-direction=asc&order-direction-field=creation&page=2&results-per-page=100&inline-relations-depth=2&include-relations=space,organization,routes
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/fe72bac0-6d22-495c-a1d8-67180461f52f/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/ca47f757-caf7-4142-803b-a577c995869f/env?order-direction=desc&order-direction-field=name&results-per-page=5&page=1
stacks/83eaeaa0-dbd0-4ff9-bb28-50adbbce4e78
shared_domains/a09e5ec7-ddc4-476d-a431-a45af446d2f2
apps/ca47f757-caf7-4142-803b-a577c995869f/service_bindings?results-per-page=100&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f/summary
shared_domains?results-per-page=100&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f/service_bindings?results-per-page=100&page=1&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=app,service_instance,service,service_plan
services/aebc001e-cf51-4d09-b5cd-d1d024685797
service_instances/b7d411a1-5ab4-4159-a34a-73b9a9b4e733/service_bindings?results-per-page=100&page=1&inline-relations-depth=1&include-relations=app
services/aebc001e-cf51-4d09-b5cd-d1d024685797/service_plans?results-per-page=100&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f?inline-relations-depth=2&include-relations=stack,space,organization,routes,domain,service_bindings
events?q=actee:ca47f757-caf7-4142-803b-a577c995869f&q=actee:ca47f757-caf7-4142-803b-a577c995869f&order-direction=desc&order-direction-field=timestamp&results-per-page=5&page=1
events?order-direction=desc&order-direction-field=timestamp&q=actee:ca47f757-caf7-4142-803b-a577c995869f&results-per-page=9&page=1
services?page=1&results-per-page=100&order-direction=desc&order-direction-field=label&inline-relations-depth=2&include-relations=service_plans
service_brokers?page=1&results-per-page=100&order-direction=desc&order-direction-field=name
service_instances?page=1&results-per-page=100&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service
service_instances?page=1&results-per-page=100&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service
organizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps
users?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=1&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces
organizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1
users/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2
organizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1&inline-relations-depth=1&include-relations=routes,service_instances,apps
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3
apps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
config/feature_flags?page=1&order-direction=desc&order-direction-field=name&results-per-page=25
buildpacks?page=1&results-per-page=100&order-direction=desc&order-direction-field=position
stacks?page=1&results-per-page=100&order-direction=desc&order-direction-field=name
security_groups?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&inline-relations-depth=1&include-relations=spaces
apps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
organizations/78ee5f44-0a33-4544-9fa8-acb0de7155ce/users?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1
users/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/user_roles?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=1&results-per-page=5&order-direction=desc&order-direction-field=creation
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1
users/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=2&results-per-page=5&order-direction=desc&order-direction-field=creation
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=1&results-per-page=5&order-direction=asc&order-direction-field=creation
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/service_instances?page=1&results-per-page=5&order-direction=desc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/service_instances?page=1&results-per-page=5&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=1&order-direction=desc&order-direction-field=creation&inline-relations-depth=1&include-relations=domain,apps
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=2&order-direction=desc&order-direction-field=creation&inline-relations-depth=2&include-relations=domain,apps
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=1&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=domain,apps
Same as above but sorted
apps?order-direction=asc&order-direction-field=creation&page=1&results-per-page=100&inline-relations-depth=2&include-relations=space,organization,routes
apps?order-direction=asc&order-direction-field=creation&page=2&results-per-page=100&inline-relations-depth=2&include-relations=space,organization,routes
apps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/0e5ac1ac-d84e-4a05-8583-0ac7621622a1/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/243d3d8b-74da-4241-af55-ce10f1e24002/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/54bd54cb-2937-49b0-9369-a8e501c405e1/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/7660ce91-f381-4528-ba01-267d55703323/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/8468ba80-d501-4197-8c33-e7df6a9555e4/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/ad346d4d-64de-424c-8d4f-48c0602c365e/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/b1e1da9b-9c20-475b-9ad8-2f838eb6daa9/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/ca47f757-caf7-4142-803b-a577c995869f?inline-relations-depth=2&include-relations=stack,space,organization,routes,domain,service_bindings
apps/ca47f757-caf7-4142-803b-a577c995869f/env?order-direction=desc&order-direction-field=name&results-per-page=5&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f/service_bindings?results-per-page=100&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f/service_bindings?results-per-page=100&page=1&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=app,service_instance,service,service_plan
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f/stats?order-direction=desc&order-direction-field=index&results-per-page=5&page=1
apps/ca47f757-caf7-4142-803b-a577c995869f/summary
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&page=1&results-per-page=5
apps/d953e846-2a6f-4570-9697-df95f789e8a0/stats?order-direction=desc&order-direction-field=index&results-per-page=5
apps/fe72bac0-6d22-495c-a1d8-67180461f52f/stats?order-direction=desc&order-direction-field=index&results-per-page=5
buildpacks?page=1&results-per-page=100&order-direction=desc&order-direction-field=position
config/feature_flags?page=1&order-direction=desc&order-direction-field=name&results-per-page=25
events?order-direction=desc&order-direction-field=timestamp&q=actee:ca47f757-caf7-4142-803b-a577c995869f&results-per-page=9&page=1
events?q=actee:ca47f757-caf7-4142-803b-a577c995869f&q=actee:ca47f757-caf7-4142-803b-a577c995869f&order-direction=desc&order-direction-field=timestamp&results-per-page=5&page=1
organizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=1&include-relations=spaces
organizations?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps
organizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=1&include-relations=spaces
organizations?page=2&results-per-page=100&order-direction=desc&order-direction-field=name&order-by=name&inline-relations-depth=2&include-relations=domains,quota_definition,private_domains,spaces,routes,service_instances,apps
organizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1
organizations/54e0be87-02f6-4b5d-b67d-40036a80f4c6/spaces?results-per-page=100&page=1&inline-relations-depth=1&include-relations=routes,service_instances,apps
organizations/78ee5f44-0a33-4544-9fa8-acb0de7155ce/users?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces
security_groups?page=1&results-per-page=100&order-direction=desc&order-direction-field=name&inline-relations-depth=1&include-relations=spaces
service_brokers?page=1&results-per-page=100&order-direction=desc&order-direction-field=name
service_instances?page=1&results-per-page=100&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service
service_instances?page=1&results-per-page=100&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service
service_instances/b7d411a1-5ab4-4159-a34a-73b9a9b4e733/service_bindings?results-per-page=100&page=1&inline-relations-depth=1&include-relations=app
services?page=1&results-per-page=100&order-direction=desc&order-direction-field=label&inline-relations-depth=2&include-relations=service_plans
services/aebc001e-cf51-4d09-b5cd-d1d024685797
services/aebc001e-cf51-4d09-b5cd-d1d024685797/service_plans?results-per-page=100&page=1
shared_domains?results-per-page=100&page=1
shared_domains/a09e5ec7-ddc4-476d-a431-a45af446d2f2
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=1&results-per-page=5&order-direction=asc&order-direction-field=creation
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=1&results-per-page=5&order-direction=desc&order-direction-field=creation
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/apps?page=2&results-per-page=5&order-direction=desc&order-direction-field=creation
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=1&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=domain,apps
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=1&order-direction=desc&order-direction-field=creation&inline-relations-depth=1&include-relations=domain,apps
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/routes?results-per-page=5&page=2&order-direction=desc&order-direction-field=creation&inline-relations-depth=2&include-relations=domain,apps
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/service_instances?page=1&results-per-page=5&order-direction=asc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/service_instances?page=1&results-per-page=5&order-direction=desc&order-direction-field=creation&inline-relations-depth=2&include-relations=service_plan,service_bindings,app,space,service
spaces/d81b4685-e04f-41f3-bc07-63a1d0ba7fa9/user_roles?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=2&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces
stacks?page=1&results-per-page=100&order-direction=desc&order-direction-field=name
stacks/83eaeaa0-dbd0-4ff9-bb28-50adbbce4e78
users?page=1&results-per-page=100&order-direction=desc&order-direction-field=username&inline-relations-depth=1&include-relations=organizations,audited_organizations,managed_organizations,billing_managed_organizations,spaces,managed_spaces,audited_spaces
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/managed_spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/organizations?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=1
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=2
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3
users/4ea175a6-418d-45d6-933f-5597ab34510c/spaces?results-per-page=100&page=3
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/managed_organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=1
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2
users/ec7c596c-1b75-4e66-aad8-2376e03dccce/organizations?results-per-page=100&page=2
users/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1
users/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1
users/f2d71b96-4268-4a29-b8a1-88c856ee7f75/spaces?results-per-page=100&page=1

V2 Specifics

Sorting/Filtering

As described elsewhere Stratos lists can be sorted and/or filtered. To support this we try to make use of sorting and filtering via the API, +however in many cases this is not possible resulting in Stratos fetching the entire list and handling sorting, filtering and pagination +locally. Obviously this is a major issue when there are large numbers of rows.

Below is a list of each endpoint and the type of sorting / filtering we use with them. Items marked in bold and italic are missing +from the v2 api.

EndpointSorted LocallySorted via APIFiltered LocallyFiltered via APIUsed API PaginationDesired Sort
apps/${guid}/statsindex in array, state, usage.mem, usage.disk, usage.cpu, uptime-state-
apps/${guid}/routeshost, port---
apps/${guid}/service_bindingscreated_at
appsname, instances, disk_quota, memory, created_at-name, organisation, spaceorganisation, space
organizations/${orgGuid}/spacesname, created_at-name-
organizationsname, created_at-name-
organizations/${guid}/usersusername-username
spacesname
spaces/${spaceGuid}/routes-created_at--YesHost
spaces/${spaceGuid}/apps-created_at--YesName, Status
spaces/${spaceGuid}/servicesnamecreated_at--
spaces/${spaceGuid}/service_instances-created_at--YesInstance name,Service name,Service Plan name,
Other endpoints
buildpacksposition, name, created_at-name-
config/feature_flagsname-name
events-timestamp-actee, typeYes
security_groupsname, created_at-name-
service_brokersname
service_instancescreated_at-name, organisation, space-
service_instances/${guid}/service_bindingscreated_at
service_plan_visibilitiesservice_plan_guid
service_plan/${guid}/service_instancescreated_at
serviceslabel, active, bindable-label
services/${guid}/service_plansname, created_at
stacksname, created_at-name
usersname, created_at-name-

``

Inline Relations

Below is a list of all the inline relations we use for each of the more fleshed out v3 endpoints of apps, spaces and organisations.

Note - Some of the one to many relations will be removed in the near future to support scaling, see Scaling

Application

EndpointInline Relations
apps
  • app --> route
  • app --> space
  • space --> org
apps/${appGuid}
  • app --> route
  • route --> domain
  • app --> space
  • space --> org
  • app --> stack
  • app --> service binding
apps/${appGuid}/routes
  • route --> domain
  • route --> application
apps/${appGuid}/service_bindings
  • service binding --> service instance
apps/${appGuid}/stats-
apps/${appGuid}/env-
apps/${appGuid}/summary-
apps/${appGuid}/routes/${routeGuid}-
apps/${appGuid}/instances/${index}-
apps/${appGuid}/restage-

Organisation

EndpointInline RelationsNotes
organizations/${orgGuid}
  • org --> space
  • space --> service instances
  • space --> apps
  • space --> routes
  • org --> domain
  • org --> quota definition
  • org --> private domains
  • org --> users
  • org --> managers
  • org --> billing managers
  • org --> auditors
organizations/${orgGuid}/spaces
  • space --> apps
  • space --> service instances
  • space --> space quota
organizations
  • org --> space
  • space --> service instances
  • space --> apps
  • space --> routes
  • org --> domain
  • org --> quota definition
  • org --> private domains
organizations/${orgGuid}/users
  • user --> orgs
  • user --> audited orgs
  • user --> managed orgs
  • user --> billing manager
  • user --> space dev
  • user --> space manager
  • user --> space auditor
We can't switch to /users?organization_guid=${guid} as this fails for no cf admins

Space

EndpointInline RelationsNotes
spaces-Note currently used, spaces are either fetchined inline with an org or via the org spaces endpoint
spaces/${spaceGuid}
  • space --> org
  • space --> domains
  • space --> routes
  • route --> domain
  • route --> applications
spaces/${spaceGuid}/routes
  • route --> domain
  • route --> application
spaces/${spaceGuid}/apps-
spaces/${spaceGuid}/user_roles-
spaces/${spaceGuid}/services
  • service --> service plan
spaces/${spaceGuid}/service_instances
  • service instance --> service bindings
  • service binding --> application
  • service instance --> service plan
  • service instance --> space
  • space --> org
  • service instance --> service

Others

The include-relations property is populated by walking our relationship tree, so for a complete and exhaustive list of all possible +relations please see the entity-factory.ts.

In terms of api requests we also make use of...

  • /buildpacks
  • /config/feature_flags
  • /events
  • /routes
  • /security_groups
  • /services
  • /service_bindings
  • /service_brokers
  • /service_instances
  • /service_plan_visibilities
  • /service_plan
  • /shared_domains
  • /stacks
  • /users

Cloud Foundry, Organisation and Space Summary Information

In the Cloud Foundry section of Stratos we show summary pages at the CF, Org and Space levels. These consist of information from the core +cf/org/space but also statistics such as number of users or memory used within that cf/org/space. +Some of these can be fetched by results-per-page of 1 and total_results, however others are derived and require fetching a large amount +of additional data, either inline with the org/space or as separate requests (Memory usage is the count of memory per instance per app). +Below is a table showing the stats at each level. The counts are respective of that level (number of routes in that specific cf, org or space)

Stat/InfoCF SummaryOrg SummarySpace Summary
No. of Appsyepyepyep
No. of App Instancesyepyep
No. of Organisationsyep
No. of Usersyepyepyep
Memory Usageyepyepyep
No. of Routesyepyep
No. of Private Domainsyep
No. of Service Instancesyepyep

V2 Summary

Current v2 Issues

  • Most lists will fetch all entities up front to provide a reasonable level of sorting and filtering
    • API provides limited sorting and filtering capabilities
    • Sorting is mostly just on creation_date
    • Filtering sometimes contains org, space and name, but not all

      Desired - Lists of entities can be sorted or filtered on any top level property

  • Calculated numerical summary stats (number of applications in an organisation, cumulative total of memory from running apps in an +organisation, number of users etc) requires fetching all entities of a certain type. This can be quite a costly set of requests.

    Desired - counts API which, given a filter, could sum up a selection of numerical properties of collection of entities. Some of this +may already be possible by making individual requests with results-per-page=1 & total_results and q filters, however a neat way to +combine these into a single request would be awesome. For instance in a single request, for an org, fetch total number of apps, app +instances, routes, etc)

  • Determining an informative application state requires an additional request to the application/<guid>/stats endpoint.

    Desired - It would massively improve Stratos performance if the APIs to list applications and retrieve a specific application could +return the app stats for the application(s). If this is not possibly, an app stats call that can return stats for all running +applications would help.

  • Fetching a list of users for non-admins can be expensive if there are many organizations.

    Desired - In an ideal world non-admins would be able to hit /users and get the same response as hitting all if their visible +organization/${guid}/users endpoints.

  • The user entities that are returned by the /users request contain a lot of duplicated organisation and space entities.

    Desired - Entities are listed in a common bucket and referenced by guid inline. Think this might be how v3 works

  • The <role>_url in a user entity can only be called by an administrator or by the same user

    Desired - URL behaves as per the /users suggestion above the response contains the organisations that are visible to the user that +calls the url

  • include-relations works by specifying the name of the child property. If the inline-relations-depth is greater than one this can lead +relations being fetched that might not actually be required

    Desired - Minor nice to have. Be able to specify relations like include-relations=application-route,route-domain

Critical v2 Features

  • Where exposed, sort order and filtering via q
  • Arbitrary entity relations can be fetched or not fetched. The way we store and retrieve entity/s would break down without this generic process
  • The API provides a url (<property name>_url) to fetch missing entity relations. As per relations, without this we'd need a process to +generically make up the url for any given relationships
+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/cf-api-v3/index.html b/website/site-dist/docs/cf-api-v3/index.html new file mode 100644 index 0000000000..276e62970f --- /dev/null +++ b/website/site-dist/docs/cf-api-v3/index.html @@ -0,0 +1,57 @@ + + + + + + +cf-api-v3 | STRATOS + + + + + + + + + + + + +
+

cf-api-v3

Cloud Foundry API v3

See Cloud Foundry API v2 Feature Usage for v2 information

  1. Comparing v2 features to v3
  2. V3 Availability
  3. Stratos Adoption of v3

Comparing v2 features to v3

V3 Docs

Entity Relations... include-relations --> include

Previously...

  • When fetching an entity, any referenced child entity or list of entities were omitted. To have them included the property name was +provided in an include-relations parameter. The covered direct child entities and children of that child entity
  • Lists of entities that were bigger than 50 were simply omitted.

Now, from my understanding, ...

  • Child entities (single or lists) are referenced by guid in the parent's relationships section
  • Child entities are also listed, with a url to fetch (like the old <property>_url property), in the links section.
  • An include parameter can be supplied which will add an included section to the entity
  • An entity in the included section is in the same format as the parent
  • include has very limited implementation
    • /apps only supports space include
    • /organization doesn't support any includes
    • /space doesn't support any includes
    • (see Cloud Foundry API v2 Feature Usage - Inline-Relations for required) +~- Unclear if include will cover chained entities aka inline-relations-depth from v2~

Collections - Pagination

  • This is covered just fine (fetch a specific page, total page count, total result count, etc)

Collections - Sorting

  • It looks like all entities can be sorted via created_at and updated_at dates, plus some also have name. Given that v2 really only +supported sorting by created_at date this should be fine for feature parity
  • However in order for Stratos to leave behind local sorting there are many missing sort fields (see Cloud Foundry API v2 Feature Usage - Sorting/Filtering)

Collections - Filtering

Entity Validation

Application State

  • For v2 info see Cloud Foundry API v2 Feature Usage - Application State
  • The improved application state string that stratos shows will be much harder to determine
    • App package_state is from a separate entity that is not linked and requires an additional request
    • App package_updated_at is from a separate entity that is not linked and requires an additional request
    • App instance state should now come form /processes and given that instance:process are now not 1:1 harder to summaries state from

V3 Availability

  • Stratos needs to support cloud foundry's with different api versions from many different providers and epochs
  • Update, many common CFs we use support some kind of v3 version.

    Note - cf-dev I haven't tested as it's unsupported on linux - see https://github.com/cloudfoundry-incubator/cfdev/issues/18 (major regression from PCFDev there)

  • Currently, it looks like neither SCF (2.84.0), IBM Cloud (2.106.0) or PCFDev (2.82.0) support v3 with includes. PWS (2.125.0) and +SAP (2.120.0) however do.

    Note - Couldn't find an easy way to determine the version of v3

Stratos Adoption of v3

Given that...

  • Endpoints are being converted to v3 iteratively, not all are available at the moment
  • Stratos will need to support v2 for a while to come (legacy installs, etc)

Then Stratos should either ..

  • Wait until v3 has feature parity with v2, create new Stratos that uses v3 and mothball versions of Stratos that talk to v2
  • Support both versions at runtime, switching each endpoint from v2 to v3 at determined cut off dates

Blocking Issues

  • Coverage of include is not on par with v2 include-relations
    • To meet parity it should support all entities in relationships and links, whether one to one or one to many
    • Currently not supported on all endpoints and does not cover enough relationships/links (see Cloud Foundry API v2 Feature Usage - Inline-Relations)
    • For instance new v3 entities are not includes (/apps - package, processes, route_mappings, environment_variables, droplets, tasks)
    • Not supported by common CFs used to develop with (SCF, PCFDev).
  • Entities do not contain all properties that were in v2 (where functionality has not changed)
    • Covers simple values and entities (one to one and one to many)
    • For instance /organizations and /spaces endpoints are not completed and contain only guid, create/updated date and name (space additionally has experimental organization)
  • Entities returned by v2/v3 endpoints are not consistent
    • For example
      • push an app with v3-push and it shows up in v2/apps
      • v3/service_bindings does not return service bindings that aren't attached to a v3 app
    • Without knowing exactly all these occurrences we won't be able to work in a mixed v2/v3 endpoint state
  • Cannot determine if a CF supports v3 or when it does support v3 which endpoints it has
    • v3 version and supported endpoints can be determined by response to <cf api url> and <cf api url>/v3
    • Getting the v2 version is simple, I don't know if there's correlation to v3 version
    • Having a v3/info which published which endpoints are supported would help a lot. Including whether include is supported
  • Chained links/relations don't appear to be supported (fetch app-->space-->org all in one request)

Frustrating Issues

  • Fetching a list of users as a non-cf admin involves making a request to every organisation (organization/${guid}/users). The response +of all of these calls contains a lot of overlapping data
  • Not all v2 endpoints exist in v3, for instance no domains, events, route, org/space quota definitions, etc
    • This would make our entity validation much more complex
  • Cannot utilise v3 pagination due to limited sorting and filtering functionality (see Cloud Foundry API v2 Feature Usage - Sorting/Filtering for missing fields)
    • This is currently on par with v2, but causes us a lot of headaches for large data sets
  • The Stratos method of calculating application state has become much harder
    • Additional requests to app /packages are required. This would be resolved if applications were linked to package
    • Would love a flag in /apps to also return the processes data. This would mean a longer request time, but we're making that request +in the frontend anyway.
  • No easy way to fetch organisation or space summary information

Stratos Tasks

Questions

  • Will include cover children of children? For instance app --> route --> domain
    • How will lists be covered? For instance organization --> space --> service instances
  • How will the deprecation of v2 endpoints happen?
    • One by one?
    • All together once v2 parity is reached?
  • Will duplicated includeed entities only appear once in a top level (entity or pagination) included? For example..conceptually..
    • Fetch an application, the application's space, the application's routes and application routes spaces all in a single request
    • If the application's space appeared in the route's space, would it only appear once in the application'sincluded section... or appear twice (once +in application included and again in route included)?
  • The style guide references a way to fetch one to many relationships as /v3/apps/:app_guid/relationships/routes (https://github.com/cloudfoundry/cc-api-v3-style-guide#viewing-1)
    • This doesn't seem to work (404), is it yet to be implemented?
    • /v3/apps/:app_guid/routes also does not work (404)
    • /v3/apps/:app_guid/route_mappings works, but there doesn't seem to be a way to include the route such that it appears in the response
  • Which version is the include=space,space.organization notation supported in?

v3 Required includes, order_by, filters, missing properties

A few UX examples have been provided, however it's quite hard to list all requirements without a deep dive into the code. Most requirements +for existing endpoints come from the need to either ..

  • Fetch properties, properties of properties, etc inline instead of making additional request. For the application wall's application list +this can be the difference between making 21 calls and then a subsequent 18 calls.. rather than receive everything with the apps request.
  • Switch from a local list (sorting and filtering done locally due to lack of support in v2) to a non-local list (pagination, sorting and +filtering done via v3 api)

/apps

TypeNamePriorityUX ExampleNotes
includespace
includeOrganization via space.organization[HIGH]Used in application wall's application list to filter local lists by org, show org name on app wall app entries, upfront fetch leading to quicker navigation to app summarySee (non-local lists for more detail on local and non-local lists).
includepackages[HIGH]See [1]Required to determine application state (state, updated_at)
includeprocesses[HIGH]See [1]Required to determine application state (instances)
includeStats via processes.stats[HIGH]See [1]Required to determine application state (state).
includecurrent_droplet[HIGH]See [1]Required to determine application state (state).
includeBuilds via packages.builds[HIGH]See [1]v3 currently has no link or relation. Required to determine application state (state).
order_bysum of processes instances count See below for notes[MEDIUM]See [2]
order_bysum of processes disk_in_mb count See below for notes[MEDIUM]See [2]
order_bysum of processes memory_in_mb count See below for notes[MEDIUM]See [2]
filterprocesses state[MEDIUM]User wishes to find all apps that have errored processes
filterorganization name[MEDIUM]See [3]
filterspace name[MEDIUM]See [3]

[1] Property/s used to determine application state without spamming requests (app state). On the application wall +page we determine the state of up to 9 apps at a time. Returning this information in a single request, or during the initial request, will +save apps x missing property's endpoints (packages, process, process stats, current_droplet, etc). This could lead to 21 concurrent calls +followed by another 18 (given the results of the first run).

[2] Enables sorting by instance count in tables. See (non-local lists for more information on local and non-local list sorting).

[3] Allows free text search by org or space name in application wall (rather than manual selection of cf, org and then space). For instance a user types part of an org name in a +special org drop down and is presented with list of apps in matching orgs. This is a short cut for the user having to scroll down a list in a +drop down.

/app/${guid}

TypeNamePriorityUX ExampleNotes
includeroute_mappings[HIGH]See [1]See [2]
includeRoute via route_mappings.route[HIGH]See [1]See [2]. /route has no v3 equivalent
includeDomain via route_mappings.route.domain[HIGH]See [1]See [2]. /domain has no v3 equivalent. Required to display complete route url. From Greg We are thinking about adding a fqdn on the routes object, which may be another way to achieve the same objective.
linksservice_bindings[HIGH]See [3]See [2]
includeservice_bindings[HIGH]See [3]See [2]
includespace
includespace.organization[HIGH]Display the name of the organisationSee [2]
includepackages[HIGH]See [4]See [2]. Required to determine application state (state, updated_at)
includeprocesses[HIGH]See [4]See [2]. Required to determine app state (instances)
includeprocesses.stats[HIGH]See [4]See [2]. Required to determine app state (state).
includecurrent_droplet[HIGH]See [4]See [2]. Required to determine app state (state).
includepackages.builds[HIGH]See [4]See [2]. v3 currently has no link or relation. Required to determine app state (state).
linksfeatures[MEDIUM]Display current app settings (ssh enabled and revisions enabled).See [2]. There's a top level ssh enabled flag, however this will show if at the app level ssh is enabled
includefeatures[MEDIUM]See aboveSee above
includedroplets[MEDIUM]We don't currently use this, however displaying these in a list to the user would be beneficial.See [2]
includetasks[MEDIUM]We don't currently use this, however displaying these in a list to the user would be beneficial.See [2]
propertystack guid/whole entityStack name is included inline in an inlined lifecycle object. This placement seems like an odd pattern. It's not an entity on it's own with it's own endpoint... but does contain an inline entity (stack). The inlined stack contains only a name and not guid/rest of stack entity. From Greg Stack is referenced by name rather than guid due to some windows usage patterns. The window's stacks are not associated with a rootfs like the linux ones are, so they can add new stacks without having to update the stacks of all windows apps..
propertybuildpack guid/whole entityAs per stack guid above. From Greg Similarly with buildpacks, having associations by name rather than guid allows for upgrades across stack versions (for example the recent upgrade from cflinuxfs2 -> cflinuxfs3) without having to re-associated apps with the new stack's version of the buildpack.
propertyenable_ssh.. or similar property to determine if ssh'ing to an instance is allowed at the app level. See /v3/apps/:guid/ssh_enabled

[1] Display bound route count & list of routes

[2] Display information quicker on the Application pages without having to make additional requests (either once for a single entity or +multiple times in the case of 1:M, for example route_mappings would require multiple requests to routes to fetch each one)

[3] Display bound service instance count & list of services, determine if a service is already bound when user is binding existing service to app, etc

[4] Property/s used to determine application state without spamming endpoints (app state).

/apps/{guid}/packages

TypeNamePriorityUX ExampleNotes
linksbuilds[HIGH]See explanation in /app/${guid} - packages.buildsSee [1]
includebuilds[HIGH]See aboveSee above
includeapp[LOW]This might come in handy in the future, more specifically if we list all packages

[1] If at some point we've fetched an app without this property we will make a separate request to fetch it, so the same includes/links are required

/apps/{guid}/processes

TypeNamePriorityUX ExampleNotes
includestats[HIGH]See explanation in /app/${guid} - processes.statsSee [1]
order_bystate[MEDIUM]In the app summary page instances tab we show a list of instances and their properties. This needs updating, but it's easy to imagine that we will display a list of processes in v3See [2]
order_bystats usage.time[MEDIUM]See aboveSee [2][See below for notes](#v3-Required-Features)
order_bystats usage.cpu[MEDIUM]See aboveSee [2][See below for notes](#v3-Required-Features)
order_bystats usage.mem[MEDIUM]See aboveSee [2][See below for notes](#v3-Required-Features)
order_bystats usage.disk[MEDIUM]See aboveSee [2][See below for notes](#v3-Required-Features)
filterstate[MEDIUM]See above

[1] If at some point we've fetched an app without this property we will make a separate request to fetch it, so the same includes/links are required

[2] This will be required in order to switch from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (non-local lists for more detail on local and non-local lists.

/service_bindings (functionality for missing /apps/{guid}/service_bindings only)

TypeNamePriorityUX ExampleNotes
linksservice_instance[HIGH]See [1]See [2]
includeservice_instance[HIGH]See aboveSee above
linksservice_instance.service[HIGH]See aboveSee above
includeservice_instance.service[HIGH]See aboveSee above
linksservice_instance.service_plan[HIGH]See aboveSee above
includeservice_instance.service_plan[HIGH]See aboveSee above
linksservice_instance.tags[HIGH]See aboveSee above
includeservice_instance.tags[HIGH]See aboveSee above
order_byservice instance name[MEDIUM]See [1]See [3]
order_byservice name[MEDIUM]See aboveSee above
order_byservice plan name[MEDIUM]See aboveSee above
filterservice instance name[MEDIUM]See aboveSee above
filterservice name[MEDIUM]See aboveSee above
filterservice plan name[MEDIUM]See aboveSee above

[1] Display a list of service instances associated with a specific application

[2] Fetching this information inline avoids making lots of additional requests

[3] This will be required in order to switch from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (non-local lists for more detail on local and non-local lists).

/spaces

TypeNamePriorityUX ExampleNotes
linksservice_instances[LOW]Show the count of service instances in the spaceIn the medium to long term we will determine this another way
includeservice_instances[LOW]See aboveSee above
linksspace_quota_definition[HIGH]Display the space quota information information per spaceSee [3]
includespace_quota_definition[HIGH]See aboveSee above
includeapplicationsPrevious requirement pre-scaling change
order_bycreated_at[MEDIUM]See [1]See [2]
order_byname[MEDIUM]See [1]See [2]
filtername[MEDIUM]See [1]. Pre-check to ensure a space name is not taken before attempting to create.See [2]

[1] Display a list of spaces in an organisation

[2] This will be required in order to switch from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (non-local lists for more detail on local and non-local lists).

[3] Avoids making additional requests. Particularly important when viewing multiple spaces at the same time.

/spaces/${guid}

TypeNamePriorityUX ExampleNotes
linksorganization[HIGH]Basic location information, display name and other informationAvoids making additional requests
includeorganization[HIGH]See aboveSee above
linksdomains[MEDIUM]Efficiency request, better to get these here than separately/domains has no v3 equivalent
includedomains[MEDIUM]See aboveSee above
linksroutes[LOW]Display the number of routes in this organisation/routes has no v3 equivalent. See [1]
includeroutes[LOW]See aboveSee above
linksroutes.domainDepending on the list of routes is bad due to scaling. We're removing this functionality
includeroutes.domainSee above
linksroutes.applicationsSee above
includeroutes.applicationsSee above
includeapplicationsPrevious requirement pre-scaling change
linksservice_instances[LOW]Display the number of service instances in this organisationSee [1]
includeservice_instances[LOW]See aboveSee above
linksservice_instances.service_bindingsDepending on the list of service instances is bad due to scaling. We're removing this functionality
`include`service_instances.service_bindings
linksspace quota[HIGH]Display quota information, when possible how close user is to various quotas, etcspace quota has no v3 equivalent
includespace quota[HIGH]See aboveSee above
propertyallow_ssh[HIGH]Display value to user. Important from an admin sense
linksspace.developers[HIGH]See [2]we might be able to fetch this via new users endpoints described in https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj
includespace.developers[HIGH]See [2]we might be able to fetch this via new users endpoints described in https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj
linksspace.managers[HIGH]See [2]we might be able to fetch this via new users endpoints described in https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj
includespace.managers[HIGH]See [2]we might be able to fetch this via new users endpoints described in https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj
linksspace.auditors[HIGH]See [2]we might be able to fetch this via new users endpoints described in https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj
includespace.auditors[HIGH]See [2]we might be able to fetch this via new users endpoints described in https://docs.google.com/document/d/1EA65UN3Xsi0EuX-3YfbFNqtJGseFr6FGBt2SR9c4Aqk/edit#heading=h.n1xhc33y2wyj

[1] Pre-scaling change. We just want the total count of entities. In the medium to long term we will determine this another way

[2] Display a list of users and their roles

/routes (functionality for `/spaces/${guid}/routes only)

Note - There doesn't seem to be a way to list routes in a space. This is separate to the concept of listing them inline in a space (with +some overlap though). This endpoint would be used to fetch a list of routes for a specific space and display them to the user. +The /v3/route_mappings endpoint provides a way to search for routes by app or route but not by space.

TypeNamePriorityUX ExampleNotes
filterspace guid[HIGH]Display a list of routes that are in a space
linksdomain[LOW]Display the url of the routeNot required if the fqdn is returned in the base route
includedomain[LOW]See aboveSee above
linksapplications[HIGH]Display a list of the apps that are bound to the routeAvoids making a request to /v3/route_mappings for each route (could be a massive amount). We expect these relations to be 1-to-not-many
includeapplications[HIGH]See aboveSee above

/service_instances (functionality for /spaces/{guid}/service_instances only)

There's lots more that could be added here when taking into account our service instance lists in places other than the space details page +(mainly including space and space.organisation).

TypeNamePriorityUX ExampleNotes
linkservice_instance.applications[HIGH]Display bound applications in a list of service instancesNot sure if this will be implemented the same as routes and route mappings, but would need similar functionality to fetch list inline. This could be replaced with a link to service_bindings and then the app for that binding
includeservice_instance.applications[HIGH]See aboveSee above
linkservice_plan[HIGH]Display service plan information per SI in a list of SISee [2]. /service_plan has no v3 equivalent
includeservice_plan[HIGH]See aboveSee above
linkservice[HIGH]Display service information per SI in a list of SISee [2] /service has no v3 equivalent
includeservice[HIGH]See aboveSee above
filterspace guid[MEDIUM]See [3]
filterorg guid[MEDIUM]See [3]
filtername[MEDIUM]See [3]
includespace[HIGH]When showing all SI in a CF fetch inlined space to space name and allow local filtering by space and org

[1] Display list of service instances in a space

[2] Avoids making additional requests per service instance

[3] This will be required in order to switch from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (non-local lists for more detail on local and non-local lists).

/user_provided_service_instances

We've recently integrated user provided service instances into Stratos. There doesn't seem to be any current support for this in v3. We'd +need similar functionality to /service_instances (where there's cross over).

/services

Comparison of missing functionality as per proposed spec in https://docs.google.com/document/d/1bDsEiZRwQJNUI41cQlUaioaY7JA1fnv_AThOI2ekPXNM/edit# +For simplicity have kept the services name instead of the proposed new name of service_offerings

TypeNamePriorityUX ExampleNotes
linkservice.service_plans[HIGH]Show a count of service plans for a service when showing a list of servicesDepends on implementation of 'included' pagination - see https://github.com/cloudfoundry/cc-api-v3-style-guide#proposal-pagination-of-related-resources
includeservice.service_plans[HIGH]See aboveSee above
linkservice.service_broker[MEDIUM]Not currently used, but would be very nice to display the broker where a service is coming fromNote - whole service broker entity (not just name), would be nice
includeservice.service_broker[MEDIUM]See aboveSee above
filtername[MEDIUM]See [1]
order_byname[MEDIUM]see [1]
order_byactive[MEDIUM]see [1]
order_bybindable[MEDIUM]see [1]

[1] As other situations where we fetch lists this will help us from switching from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (non-local lists for more detail on local and non-local lists).

/service/${guid}

See /services above

spaces/${guid}/services

To be replaced with /services

services/${guid}/service_plans

Currently missing in v3 docs. If implemented would need the same link/includes as service_bindings section below

service_bindings (POST)

This looks good

service_bindings/${guid} (DELETE)

This looks good

service_bindings

We don't currently use this, but in order for us to we would need the following

TypeNamePriorityUX ExampleNotes
includeservice_binding.service_instance[HIGH]
includeservice_binding.app[HIGH]
filterservice instance name[MEDIUM]See [1]
filterapplication name[MEDIUM]See [1]
order_byservice instance name[MEDIUM]see [1]
order_byapplication name[MEDIUM]see [1]

[1] As other situations where we fetch lists this will help us from switching from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (non-local lists for more detail on local and non-local lists).

service_bindings/${guid}

We don't currently use this, but in order for us to we would need the same as above (list service_bindings)

service_brokers

We don't currently use this but it would be very nice to. In order for us to though we would need the following

TypeNamePriorityUX ExampleNotes
linkservice_broker.space[HIGH]
includeservice_broker.space[HIGH]
linkservice_broker.service_offerings[HIGH]For a given broker show a list of service offerings without making multiple requests
includeservice_broker.service_offerings[HIGH]See above
filterservice broker name[MEDIUM]See [1]
filterspace guid[MEDIUM]See [1]
order_byservice broker name[MEDIUM]see [1]

[1] As other situations where we fetch lists this will help us from switching from local (fetch allll entities in a list and sort locally) to non-local (use CF api pagination including sorting). See (non-local lists for more detail on local and non-local lists).

service_brokers/{guid}

We don't currently use this, but in order for us to we would need the same as above (list service_bindings)

v3 Required Features

Single 'included` section per request

There should hopefully be a single included section even if included elements have their own includes. Not quite a requirement, but a real nice to have.

included lists

Ability to set include for lists of entities. See https://github.com/cloudfoundry/cc-api-v3-style-guide#proposal-pagination-of-related-resources

Use case - Routes, packages, builds, process stats, etc in an application

order_by values in included entities

Ability to use properties of entities that are from the included section in order_by.

Covers simple case of sorting by a property in a 1:1 include and also summation of numerical properties in 1:M relationship.

Use case - sort applications by instance count. Requires process as an include and ability to sort applications by sum of processs instance values

Use case - as above, but instead of instances the sum of memory in a processes memory_in_mb. Need to consider whether processes state value should be taken into account (only include processes that are running)

Use case - as above, but the sum of processes stats usage.mem.

filter values in included

As per order_by, delve into an included entity and filter out given a specific path.

Use case - Filter a list of service bindings by service instance name, service name or service plan name

Use case - Filter a list of apps by organization or space

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/cf-entity-scaling/index.html b/website/site-dist/docs/cf-entity-scaling/index.html new file mode 100644 index 0000000000..88f1cb98dc --- /dev/null +++ b/website/site-dist/docs/cf-entity-scaling/index.html @@ -0,0 +1,39 @@ + + + + + + +cf-entity-scaling | STRATOS + + + + + + + + + + + + +
+

cf-entity-scaling

Cloud Foundry Scaling - How Stratos Handles Large Lists

Stratos presents collections of entities via the Stratos list component. The list component presents the collection in a paginated, sortable and searchable way in either a set of cards or a table. +In order to achieve this, due to the limitations of the APIs used, the list may fetch all entities (as opposed to fetching entities for the visible page only) and paginate, sort and search locally.

Protecting Stratos from Large Collections

In some cases the number of entities in a collection can be incredibly high. Stratos can decide to not fetch them all in order to protect the CF from +a substantial number of requests. To do this the first page is fetched and the total number of entities is checked against a limit. If under +the limit the remaining pages are asynchronously fetched. If over then the remaining pages are ignored and the user is informed that the list could not fetch all entities.

Depending on the list, the user can then try to filter the collection such that the number of entities is below the limit. Depending on configuration +the user also has the option to fetch all entities regardless of the limit.

Applicable Lists

Currently, in 3.1.0, this large collection protection is only applicable to the following lists

  • Application Wall
  • Marketplace (Services)
  • Services (Service & User Provided Service Instances)
  • CF, Organisation and Space Users
  • CF Routes

In the future we hope to expand this to all lists.

Determining the List Limit

The limit at which we won't fetch all entities is determined, in least important to most important order, by

1) The global CF default - 600 +2) The Jetstream override for all lists - by default not set

In the future we hope to allow each end user of Stratos to determine their own limit (if they have the correct permissions).

Fetch All feature

If the list hits the limit the user will be presented with a button to Fetch All entities. Clicking this button ensures the list reverts +back as if there were no limit and thus fetching all entities. This feature is disabled by default and can be enabled by a Jetstream override.

Configuration

The Jetstream overrides can be set via environment variable, or if in helm, as values.

Environment VariableHelm ValueDescriptionDefault
UI_LIST_MAX_SIZEconsole.ui.listMaxSizeOverride the default maximum number of entities that a configured list can fetch. When a list meets this amount additional pages are not fetched
UI_LIST_ALLOW_LOAD_MAXEDconsole.ui.listAllowLoadMaxedIf the maximum list size is met give the user the option to fetch all resultsfalse
+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/deploy/access/index.html b/website/site-dist/docs/deploy/access/index.html new file mode 100644 index 0000000000..2cc5c4cf9c --- /dev/null +++ b/website/site-dist/docs/deploy/access/index.html @@ -0,0 +1,40 @@ + + + + + + +Accessing Stratos | STRATOS + + + + + + + + + + + + +
+

Accessing Stratos

Depending on the deployment mode, you may require access to an UAA. Stratos also has the option to configure a local user account which removes the need for a UAA in non-Cloud Foundry deployments.

Cloud Foundry deployment

In a Cloud Foundry deployment, the Console will be configured to use the UAA used by the Cloud Foundry instance. +Therefore, the login credentials will be the CF credentials for the user. A Cloud Foundry administrator (a user with the cloud_controller.admin scope) will also be a Console administrator.

Kubernetes deployment

In a Kubernetes deployment using Helm, no UAA instance is deployed. Users have the choice to either provide their own UAA to authenticate against, or alternatively Stratos may be configured at deployment, to use a local user account.

Docker, single container deployment

The single container deployment does not contain a UAA. The instructions specified for a Kubernetes deployment apply to this, including the local user account option.

Console Login

Log in to Stratos With UAA

The Console will start in a setup mode and users will be need to provide the following to complete the setup:

  1. UAA Endpoint
  2. Is SSL Validation should be enforced
  3. Username and password for a user who has required Console administrator scope
  4. The UAA Client ID and client secret

Once the user provides this information, the user will be able to select the scope which should be used to identify a Console admin.

Log in to Stratos with local user account

Helm deployment

With local user account configured, the console will present the login screen on startup. Log in with username: admin, and the password you configured in the Stratos deployment command. The local user account has admin permissions.

Docker, single container deployment

Log in to the console using the local user credentials you configured when building/deploying the container.

Quickly setting up a UAA for development

  1. We will setup two containers that are linked to each other
$ docker network create --driver=bridge dev-bridge
  1. Bring up the single container Console
$ docker run -p 4443:443 --net=dev-bridge splatform/stratos --name console
  1. Bring up the UAA
$ docker run --net=dev-bridge --name=uaa --rm splatform/stratos-uaa
  1. Access the Console at http://localhost:4443/ and provide the following information: +UAA Endpoint API URL: http://uaa:8080 +Client ID: console +Client Secret: Leave this blank +Admin Account: admin +Password: hscadmin

  2. Click enter and select the following from the list: +stratos.admon

  3. The Console is now ready to be used

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/deploy/all-in-one/index.html b/website/site-dist/docs/deploy/all-in-one/index.html new file mode 100644 index 0000000000..7c0ecd1f67 --- /dev/null +++ b/website/site-dist/docs/deploy/all-in-one/index.html @@ -0,0 +1,46 @@ + + + + + + +Deploying with the All-In-One Docker Container | STRATOS + + + + + + + + + + + + +
+

Deploying with the All-In-One Docker Container

The all-in-one container sets up the Stratos components in a single container.

Requirements:

You will need to have installed Docker, see Docker Installation Documentation.

Quick Start

Run Stratos in Docker locally:

$ docker run -p 4443:443 splatform/stratos:latest

Once that has finished, you can then access Stratos by visiting https://localhost:4443.

You can configure a local admin account and set the password for future logins.

Note regarding the Stratos Session Store Secret

Stratos uses a secret to protect the Session cookie it uses to identify users. By default it will generate a random value for this secret.

We recommend configuring an alphanumeric secret of your choice by setting the SESSION_STORE_SECRET environment variable.

This can be done by adding the following to the docker run command shown in the section below:

-e SESSION_STORE_SECRET=<alphanumeric secret>

Configuring a local user account in place of a UAA

By default the All-in-one image requires a UAA for user authentication. If this is not desired, the image can be configured to use a Stratos local user account. Edit the file deploy/all-in-one/config.all-in-one.properties and uncomment the following lines before building the container.

#AUTH_ENDPOINT_TYPE=local
#LOCAL_USER=localuser
#LOCAL_USER_PASSWORD=localuserpass
#LOCAL_USER_SCOPE=stratos.admin

Building the container:

To build the container, change directory to the root of the project and open a command prompt:

build/store-git-metadata.sh
docker build -f deploy/Dockerfile.all-in-one . -t stratos-aio

Note: The Dockerfile for all-in-one is in the deploy folder and not the deploy/all-in-one folder.

Note: If you are using Docker for Mac and you get an error 137 when building, you should increase the memory available to Docker (via Preferences > Advanced) and try again.

Bring up the container with:

docker run -p 4443:443 stratos-aio

Stratos should now be accessible at the following URL:

https://localhost:4443

If using a UAA, you will be presented with the Stratos Setup welcome screen - you will need to enter your UAA information to configure Stratos. Once complete, you will be able to login with your credentials. If you have configured the container to use a local user account instead of a UAA, log in with the credentials specified in the configuration file.

Persisting the Database

Each time you start and stop the Docker All-In-One container, you will lose any your UAA configuration, endpoints and connections that you have made in Stratos.

In order to persist the Stratos database file between runs of the Docker container you can store the database file outside of the docker container.

Create a folder where the database folder will be stored, e.g.

mkdir -p ~/stratos-db

When starting the Docker container, mount a volume for this folder and pass this via the SQLITE_DB_DIR environment variable, e.g.

docker run -p 4443:443 -v ~/stratos-db:/var/stratos-db -e SQLITE_DB_DIR=/var/stratos-db stratos-aio

Now each time you stop and start the container, Stratos will maintain the database file.

Note: You can validate that the environment variable has been correctly set and check the database file location by observing the log file +of the Docker container. You should see a log message similar to: SQLite Database file: /var/stratos-db/console-database.db

Pushing the All-In-One Docker Image to Cloud Foundry

Note: We recommend setting the session store secret - please use a manifest file for this and set the SESSION_STORE_SECRET environment variable.

The All-In-One Docker Image can be pushed to Cloud Foundry.

Firstly, build the image and push it to a Docker registry, so that it is available to Cloud Foundry, e.g. to build and push to Docker Hub, in the project root directory run:

build/store-git-metadata.sh
docker build -f deploy/Dockerfile.all-in-one . -t MY-DOCKER-ORG/stratos-aio:latest
docker push MY-DOCKER-ORG/stratos-aio:latest

Where MY-DOCKER_ORG is your Docker Hub organization.

You can now push this image directly to Cloud Foundry with:

cf push stratos --docker-image MY-DOCKER-ORG/stratos-aio:latest

The log output of the push command will include the URL where the Stratos application can be accessed in a browser, e.g.

> cf push stratos --docker-image MY-DOCKER-ORG/stratos-aio:latest
Creating app stratos in org e2e / space e2e as admin...
OK
+
Creating route stratos.local.pcfdev.io...
OK
+
Binding stratos.local.pcfdev.io to stratos...
OK
+
+
Starting app stratos in org e2e / space e2e as admin...
Creating container
Successfully created container
Staging...
Staging process started ...
Staging process finished
Exit status 0
Staging Complete
Destroying container
Successfully destroyed container
+
1 of 1 instances running
+
App started
+
+
OK
+
App stratos was started using this command `./jetstream `
+
Showing health and status for app stratos in org e2e / space e2e as admin...
OK
+
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: stratos.local.pcfdev.io <-- URL
last uploaded: Mon Dec 3 03:12:47 UTC 2018
stack: cflinuxfs2
buildpack: unknown
+
state since cpu memory disk details
#0 running 2018-12-03 03:12:54 AM 0.0% 0 of 256M 0 of 512M

Note: In this example we are pushing with the application name stratos

Note: By default the All-in-one image has SSL Validation disabled when authenticating with Cloud Foundry and the UAA - this allows it to work out of the box with environments like PCF Dev. If this is not the behavior you desire, edit the file deploy/all-in-one/config.all-in-one.properties and change the SKIP_SSL_VALIDATION as desired before building and publishing the image.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/deploy/cloud-foundry/cf-troubleshooting/index.html b/website/site-dist/docs/deploy/cloud-foundry/cf-troubleshooting/index.html new file mode 100644 index 0000000000..e35a3a035d --- /dev/null +++ b/website/site-dist/docs/deploy/cloud-foundry/cf-troubleshooting/index.html @@ -0,0 +1,33 @@ + + + + + + +Troubleshooting Cloud Foundry Deployment | STRATOS + + + + + + + + + + + + +
+

Troubleshooting Cloud Foundry Deployment

Creating logs for recent deployments

To create a log file of the push

cf push | tee cfpush.log

To create a log file of recent console output

cf logs console --recent | tee cfconsole.log

NOTE If the name of the application has been changed from console in the manifest file please also change the name in the logs statement

Turning on backend debugging logs

The LOG_LEVEL environment variable controls the backend logs

cf set-env console LOG_LEVEL debug
cf restart console
cf logs console

would output more debugging output such as

2018-10-24T14:47:36.91+0200 [RTR/1] OUT console.my.domain - [2018-10-24T12:47:36.850+0000] "GET /pp/v1/-o1F0L956QhAIK7R56Uc1lMh5L4/apps/3ddc0bc6-a645-4449-9d1b-6fe86146cf61/ssh/0 HTTP/1.1" 500 0 0 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0" "10.228.194.8:42182" "192.168.35.91:61044" x_forwarded_for:"10.228.194.8" x_forwarded_proto:"https" vcap_request_id:"182dddeb-d877-4d58-45f7-0bd886d1caf6" response_time:0.066925325 app_id:"0ba408ef-d0e6-4ab8-96bb-0bc078b8d8fb" app_index:"0" x_b3_traceid:"d166622a0d612fea" x_b3_spanid:"d166622a0d612fea" x_b3_parentspanid:"-"
2018-10-24T14:47:36.91+0200 [RTR/1] OUT
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] sessionCleanupMiddleware
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] errorLoggingMiddleware
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT INFO[Wed Oct 24 12:47:36 UTC 2018] Not redirecting this request
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] getSession
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] getSessionValue
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] getSession
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] setStaticContentHeadersMiddleware
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] urlCheckMiddleware
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] sessionMiddleware
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] getSessionValue
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] getSession
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] xsrfMiddleware
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] GetCNSIRecord
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] Find
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] decryptToken
2018-10-24T14:47:36.85+0200 [APP/PROC/WEB/0] OUT DEBU[Wed Oct 24 12:47:36 UTC 2018] Decrypt
[...]

Application Security Groups

If you have problems when deploying Stratos as a Cloud Foundry application, check that the Application Security Group you have will allow Stratos to communicate with the Cloud Foundry API.

For information on the default ASGs, see here.

To configure a new ASG for the organization and space that are using Stratos, first create a new ASG definition, for example:

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/deploy/cloud-foundry/cloud-foundry/index.html b/website/site-dist/docs/deploy/cloud-foundry/cloud-foundry/index.html new file mode 100644 index 0000000000..5c05946c99 --- /dev/null +++ b/website/site-dist/docs/deploy/cloud-foundry/cloud-foundry/index.html @@ -0,0 +1,44 @@ + + + + + + +Deploying as a Cloud Foundry Application | STRATOS + + + + + + + + + + + + +
+

Deploying as a Cloud Foundry Application

Deployment Steps

Stratos can be pushed as an application to Cloud Foundry.

You can do it in two ways:

  1. Deploy Stratos from source
  2. Deploy Stratos from docker image

You will then be able to open a web browser and navigate to the console URL:

https://console.<DOMAIN>

Where <DOMAIN> is the default domain configured for your Cloud Foundry cluster.

To login use the following credentials detailed here.

If you run into issues, please refer to the Troubleshooting Guide below.

The console will pre-configure the host Cloud Foundry endpoint. No other CF instance should be registered unless the instructions in +the section Associate Cloud Foundry database service are followed. +All other deployment methods (helm, docker all-in-one, etc) allow the registration of multiple CF instances by default.

Note:

  1. You need the cf CLI command line tool installed and available on the path.
  2. You need to have configured the cf cli to point to your Cloud Foundry cluster, to be authenticated with your credentials and to be targeted at the organization and space where you want the console application be created.
  3. You may need to configure Application Security Groups on your Cloud Foundry Cluster in order that Stratos can communicate with the Cloud Foundry API. See below for more information.
  4. The Stratos Console will automatically detect the API endpoint for your Cloud Foundry. To do so, it relies on the cf_api_url value inside the VCAP_APPLICATION environment variable. If this is not provided by your Cloud Foundry platform, then you must manually update the application manifest as described below.

Running Stratos in Production Environments

Please be aware of the following when running Stratos in a production environment:

Configure a Session Store Secret

Stratos uses a Session Store Secret to protect the user session cookie. We recommend that you set your own value for this secret - choosing an alphanumeric string of your choice.

You can configure this secret by editing the application manifest and adding to the env section, e.g.

applications:
- name: console
... memory, disk settings here
env:
SESSION_STORE_SECRET: <your session store secret here>

Pre-configure UAA client used for user invites

You can skip this step and configure any CFs invite clients via the Stratos UI.

To set the UAA client for user invites, supply the client id and client secret as environment variables as shown below:

INVITE_USER_CLIENT_ID=<UAA_CLIENT_ID>
INVITE_USER_CLIENT_SECRET=<UAA_CLIENT_SECRET>

This will set the the UAA client and UAA secret used to invite users for the default CF only.

See the invite users guide for more information about user invites in Stratos.

Use of the Default Embedded SQLite Database

We do not recommend deploying Stratos to a production environment using the default embedded SQLite Database. Instead we recommend creating +and binding a database service instance to Stratos - for more information see here.

Deploy Stratos from source

To do so, clone the stratos repository, cd into the newly cloned repository and push to Cloud Foundry. This can be done with:

git clone https://github.com/cloudfoundry/stratos
cd stratos
git checkout tags/stable -b stable
./build/store-git-metadata.sh
cf push

If the cf push exceeds the time allowed see the instructions here

Pre-building the UI

Due to the memory usage of the Angular compiler (see below), when deployed to Cloud Foundry via cf push, Stratos does not use AOT (Ahead-of-Time) compilation.

If you wish to enable AOT or reduce the push time, you can pre-build the UI before pushing.

This can be done with:

git clone https://github.com/cloudfoundry/stratos
cd stratos
npm install
npm run prebuild-ui
cf push

You will need a recent version of Node installed locally to do this.

The prebuild-ui npm script performs a build of the front-end UI and then zips up the resulting folder into a package named stratos-frontend-prebuild.zip. The Stratos buildpack will unpack this zip file and use its contents instead of building the UI during staging, when this file is present.

Memory Usage

The Stratos Cloud Foundry manifest.yml states that the application requires +1512MB of memory. This is required during the build process of the +application since building an angular2 app is a memory intensive process. The +memory limit can be scaled down after the app has been pushed, using the cf CLI.

Deploy Stratos from docker image

Deploy Stratos using the splatform/stratos docker image

NOTE: Your Cloud Foundry must have docker support enabled.

cf push console -o splatform/stratos:stable -m 128M -k 384M

Note: You can replace console in the command above with a name of your choice for the application

Alternatively cf push using a manifest

  • download manifest-docker.yml or create your own manifest file:
    applications:
    - name: console
    docker:
    image: splatform/stratos:stable
    instances: 1
    memory: 128M
    disk_quota: 384M
  • now, you can simply push it to Cloud Foundry:
    cf push -f manifest-docker.yml

Associate Cloud Foundry database service

Follow instructions here.

Use SSO Login

By default Stratos will present its own login UI and only supports username and password authentication with your UAA. You can configure Stratos to use UAA's login UI by specifying the the SSO_LOGIN environment variable in the manifest, for example:

applications:
- name: console
... memory, disk settings here
env:
SSO_LOGIN: true

When SSO Login is enabled, Stratos will also auto-connect to the Cloud Foundry it is deployed in using the token obtained during the SSO Login flow.

For more information - see Single-Sign On.

[
{
"destination":"0.0.0.0-255.255.255.255",
"protocol":"all"
}
]

Save this to a file, e.g. my-asg.json.

Note: this allows example all network traffic on all IP ranges - we don't recommend using this.

Unbind the existing ASG for you organization (ORG) and space (SPACE) with:

cf unbind-security-group public_networks ORG SPACE

Create a new ASG using the definition you saved to a file and give it a name, with:

cf create-security-group NAME my-asg.json

Bind this ASG to your ORG and SPACE with:

cf bind-security-group NAME ORG SPACE

Console fails to start

The Stratos Console will automatically detect the API endpoint for your Cloud Foundry. To do so, it relies on the cf_api value inside the VCAP_APPLICATION environment variable. +To check if the variable is present, use the CF CLI to list environment variables, and inspect the VCAP_APPLICATION variable under System-Provided.

$ cf env console
Getting env variables for app console in org SUSE / space dev as admin...
OK
+
System-Provided:
+
+
{
"VCAP_APPLICATION": {
"application_id": ...,
"application_name": "console",
"application_uris": ...
"application_version": ...,
"cf_api": "http://api.cf-dev.io",
...
}
+
No user-defined env variables have been set
...

If the cf_api environment variable is absent then set the CF_API_URL variable. See the following Setting the CF_API_URL env variable in the manifest section.

However, if the cf_api environment variable is present, and an HTTP address is specified, it is possible that insecure traffic may be blocked. See the following Setting the CF_API_FORCE_SECURE env variable in the manifest section.

Setting the CF_API_URL env variable in the manifest

To specify the Cloud Foundry API endpoint, add the CF_API_URL variable to the manifest, for example:

applications:
- name: console
memory: 256M
disk_quota: 256M
host: console
timeout: 180
buildpack: https://github.com/cloudfoundry/stratos-buildpack
health-check-type: port
env:
CF_API_URL: https://<<CLOUD FOUNDRY API ENDPOINT>>>

Setting the CF_API_FORCE_SECURE env variable in the manifest

To force the console to use secured communication with the Cloud Foundry API endpoint (HTTPS rather than HTTP), specify the CF_API_FORCE_SECURE environment in the manifest, for example:

applications:
- name: console
memory: 256M
disk_quota: 256M
host: console
timeout: 180
buildpack: https://github.com/cloudfoundry/stratos-buildpack
health-check-type: port
env:
CF_API_FORCE_SECURE: true
+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/deploy/cloud-foundry/db-migration/index.html b/website/site-dist/docs/deploy/cloud-foundry/db-migration/index.html new file mode 100644 index 0000000000..f578b58f27 --- /dev/null +++ b/website/site-dist/docs/deploy/cloud-foundry/db-migration/index.html @@ -0,0 +1,36 @@ + + + + + + +Associate a Cloud Foundry database service | STRATOS + + + + + + + + + + + + +
+

Associate a Cloud Foundry database service

As described in the standard cf push instructions here Stratos, when deployed via cf push, +does not contain any way to persist data over application restarts and db entries such as registered endpoints +and user tokens are lost. To resolve this a Cloud Foundry db service can be bound to to it. Run through +the steps below to implement.

  1. Create a Database Service Instance

    NOTE Stratos supports postgresql and mysql DBs. Stratos will enumerate the bound service instances to detect the database type - see below for more detail.

    Use cf create-service to create a service instance for the DB - for example:

    cf create-service postgresql v9.4 console_db
    • In this example, postgresql is the service name for the Postgres DB service, v9.4 is the service plan and console_db is the name for the service instance that will be created.
    • To view services and service plans:
      cf marketplace

    You can also create an User-Provided Service Instance:

    cf cups console_db -p '{"uri": "postgres://", "username":"console_appuser", "password":"***", "hostname":"192.168.12.34", "port":"5432", "dbname":"console_db" }'
  2. Associate the new service with Stratos via the Manifest

    • Add the service name to the services section of Stratos's manifest.yml, for example:
      services:
    • console_db
    • This specifies that Stratos should bind to the service instance named console_db
  3. Push the app via cf push

    cf push

Note on Service Bindings

Stratos will look through all service instances that are bound to it and filter those to determine which are database services. It determines:

  • A Postgres database service if it has a uri field in the credentials object which begins with the string "postgres://" or it has a tag "postgresql"

  • A MySQL database service if it has a uri field in the credentials object which begins with the string "mysql://" or it has a tag "mysql"

If there is a single database service instance, Stratos will use that.

If there are multiple database service instances, Stratos will look for one with a tag of "stratos".

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/deploy/deploy-overview/index.html b/website/site-dist/docs/deploy/deploy-overview/index.html new file mode 100644 index 0000000000..28a60eb4e2 --- /dev/null +++ b/website/site-dist/docs/deploy/deploy-overview/index.html @@ -0,0 +1,33 @@ + + + + + + +Deploying Stratos | STRATOS + + + + + + + + + + + + +
+

Deploying Stratos

Stratos can be deployed in the following environments:

  1. Cloud Foundry, as an application. See guide
  2. Kubernetes, using a Helm chart. See guide
  3. Docker, single container deploying all components. See guide

Note: that not all features are enabled in every environment - the Kubernetes deployment supports all features, but Cloud Foundry and Docker deployments do not support some features.

Note: Some features are marked as 'Tech Preview' and are only available if tech preview features are enabled when deploying.

Deployed in Cloud Foundry as an application

In this case, Stratos is deployed in a manner optimized for the management of a single Cloud Foundry instance. The 'Endpoints Dashboard' that allows multiple Cloud Foundry endpoints to be registered is not deployed. An extra component is deployed that detects that the Console is running as Cloud Foundry which does the following:

  • Automatically detects the Cloud Foundry endpoint and located the UAA Endpoint to use for authentication
  • Authenticates directly against the UAA for the Clound Foundry where the Console is deployed and assumes that Cloud Foundry admins are also Console admins (the UAA Scope 'cloud_controller.admin' is used to identify admins)
  • Uses a SQLite database rather than Postgres
  • Automatically connects to the Cloud Foundry endpoint when a user logs in to simplify the user flow when using the Console in this case

In this case, the front-end web application static resources are served by the API Server back-end rather than a separate web server.

By defaut, a non-persistent SQLite database is used - by automatically registering the cloud foundry endpoint and connecting to it on login, all data stored in the database can be treated as ephimeral, since it will be re-created next time a user logs in. Cloud Foundry Session Affinity is used to ensure that when scaling up the Console Application to multiple instances, the user is also directed to the instance which will know about them and their endpoints (since each Application instance will have its own local SQLite store).

Alternatively, Stratos can be configured with a persistent Cloud Foundry database service, which enables features requiring persistence such as user favorites.

Deployed in Kubernetes

In this case, a Helm chart is used to deploy the Console into a Kubernetes environment.

At the outer-level there are two services - the external service that provides the Console itself and a private service that provides a Postgres DB to the Console service.

The Console service is provided by a deployment consisting of two containers, one providing the static front-end web application resources, served by an nginx instance, the other providing the API Server back-end.

Deployed in Docker using a single container

In this case, a single Docker image is run in a container that hosts all services together. SQLite is used as the database, so any endpoint metadata registered is lost when the container is destroyed.

This deployment is recommended only for trying out the Console and for development.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/deploy/kubernetes/helm-installation/index.html b/website/site-dist/docs/deploy/kubernetes/helm-installation/index.html new file mode 100644 index 0000000000..03993e34f2 --- /dev/null +++ b/website/site-dist/docs/deploy/kubernetes/helm-installation/index.html @@ -0,0 +1,39 @@ + + + + + + +Deploying Using Helm | STRATOS + + + + + + + + + + + + +
+

Deploying Using Helm

Stratos is an Open Source Web-based Management console for Cloud Foundry. It allows users and administrators to both manage applications running in the Cloud Foundry cluster and perform cluster management tasks.

Installation

Stratos can be installed to a Kubernetes cluster using Helm. Either Helm 2 or Helm 3 can be used, although we recommend using the newer Helm 3 version.

Ensure the Helm client and kubectl CLIs are installed. If you are using Helm 2, ensure you've initialized Tiller into your cluster with the appropriate +Service Account.

The Helm chart is published to the Stratos Helm repository.

You will need to have the Stratos Helm repository added to your Helm setup, if you do not, run:

helm repo add stratos https://cloudfoundry.github.io/stratos

Check the repository was successfully added by searching for the console, for example:

helm search repo console
NAME CHART VERSION APP VERSION DESCRIPTION
stratos/console 3.2.0 3.2.0 A Helm chart for deploying Stratos UI Console

Note: Version numbers will depend on the version of Stratos available from the Helm repository

Note: Commands shown in this document are for Helm version 3. For Helm version 2, when installing, instead of supplying the name via the --name flag, it is supplied as the first argument, before the chart name.

To install Stratos:

kubectl create namespace console
helm install my-console stratos/console --namespace=console

Note: The first kubectl command will create a namespace for Stratos. With Helm 3 you must create a namespace before installing. +We recommend installing Stratos into a separate namespace.

Note: This assumes that a storage class exists in the Kubernetes cluster that has been marked as default. If no such storage class exists, a specific storage class needs to be specified, please see the following section Specifying a custom Storage Class.

You can change the namespace (--namespace) and the release name to values of your choice.

This will create a Stratos instance named my-console in a namespace called console in your Kubernetes cluster.

After the install, you should be able to access the Console in a web browser by following the instructions below.

Advanced installation topics are covered in the the Advanced Topics section below.

Helm Chart Configuration

The following table lists the configurable parameters of the Stratos Helm chart and their default values.

ParameterDescriptionDefault
imagePullPolicyImage pull policyIfNotPresent
console.sessionStoreSecretSecret to use when encrypting session tokensauto-generated random value
console.ssoLoginWhether to enable SSO Login and use the UAA Login UI instead of the built-in onefalse
console.backendLogLevelLog level for backend (info, debug)info
console.service.externalIPsExternal IPs to add to the console service[]
console.service.loadBalancerIPIP address to assign to the load balancer for the metrics service (if supported)
console.service.loadBalancerSourceRangesList of IP CIDRs allowed access to load balancer (if supported)[]
console.service.typeService type for the console (ClusterIP, NodePort, LoadBalancer, ExternalName etc)ClusterIP
console.service.servicePortService port for the console service443
console.service.externalNameExternal name for the console service when service type is ExternalName
console.service.nodePortNode port to use for the console service when service type is NodePort or LoadBalancer
console.ingress.enabledEnable ingress for the console servicefalse
console.ingress.hostHost for the ingress resource
console.ingress.secretNameName of an existing secret containing the TLS certificate for ingress
console.service.http.enabledEnabled HTTP access to the console service (as well as HTTPS)false
console.service.http.servicePortService port for HTTP access to the console service when enabled80
console.service.http.nodePortNode port for HTTP access to the console service (as well as HTTPS)
console.templatesConfigMapNameName of config map that provides the template files for user invitation emails
console.userInviteSubjectEmail subject of the user invitation message
console.techPreviewEnable/disable Tech Preview featuresfalse
console.ui.listMaxSizeOverride the default maximum number of entities that a configured list can fetch. When a list meets this amount additional pages are not fetched
console.ui.listAllowLoadMaxedIf the maximum list size is met give the user the option to fetch all resultsfalse
console.localAdminPasswordUse local admin user instead of UAA - set to a password to enable
console.tlsSecretNameSecret containing TLS certificate to use for the Console
console.mariadb.externalUse an external database instead of the built-in MariaDBfalse
console.mariadb.databaseName of the database to useconsole
console.mariadb.userName of the user for accessing the databaseconsole
console.mariadb.userPasswordPassword of the user for accessing the database. Leave blank for the built-in database to generate a random password
console.mariadb.rootPasswordPassword of the root user for accessing the database. Leave blank for the built-in database to generate a random password
console.mariadb.hostHostname of the database when using an external db
console.mariadb.portPort of the database when using an external db3306
console.mariadb.tlsTLS mode when connecting to database (true, false, skip-verify, preferred)false
uaa.endpointURL of the UAA endpoint to authenticate with
uaa.consoleClientClient to use when authenticating with the UAAcf
uaa.consoleClientSecretClient secret to use when authenticating with the UAA
uaa.consoleAdminIdentifierScope that identifies an admin user of Stratos (e.g. cloud_controller.admin
uaa.skipSSLValidationSkip SSL validation when when authenticating with the UAAfalse
env.SMTP_AUTHAuthenticate against the SMTP server using AUTH command when Sending User Invite emailsfalse
env.SMTP_FROM_ADDRESSFrom email address to use when Sending User Invite emails
env.SMTP_USERUser name to use for authentication when Sending User Invite emails
env.SMTP_PASSWORDPassword to use for authentication when Sending User Invite emails
env.SMTP_HOSTServer host address to use for authentication when Sending User Invite emails
env.SMTP_PORTServer port to use for authentication when Sending User Invite emails
kube.authSet to "rbac" if the Kubernetes cluster supports Role-based access control"rbac"
kube.organizationRegistry organization to use when pulling images
kube.registry.hostnameHostname of registry to use when pulling imagesdocker.io
kube.registry.usernameUsername to use when pulling images from the registry
kube.registry.passwordPassword to use when pulling images from the registry
console.podAnnotationsAnnotations to be added to all pod resources
console.podExtraLabelsAdditional labels to be added to all pod resources
console.statefulSetAnnotationsAnnotations to be added to all statefulset resources
console.statefulSetExtraLabelsAdditional labels to be added to all statefulset resources
console.deploymentAnnotationsAnnotations to be added to all deployment resources
console.deploymentExtraLabelsAdditional labels to be added to all deployment resources
console.jobAnnotationsAnnotations to be added to all job resources
console.jobExtraLabelsAdditional labels to be added to all job resources
console.service.annotationsAnnotations to be added to all service resources
console.service.extraLabelsAdditional labels to be added to all service resources
console.service.ingress.annotationsAnnotations to be added to the ingress resource
console.service.ingress.extraLabelsAdditional labels to be added to the ingress resource
console.nodeSelectorNode selectors to use for the console Pod
mariadb.nodeSelectorNode selectors to use for the database Pod
configInit.nodeSelectorNode selectors to use for the configuration Pod

Accessing the Console

To check the status of the instance use the following command:

helm status my-console

Note: Replace my-console with the value you used for the name parameter, or if you did not provide one, use the helm list command to find the release name that was automatically generated for you.

The console is exposed via an HTTPS service - RELEASE-NAME-ui-ext (where RELEASE-NAME is the name used for the name parameter when installing). You can find the details of this service with:

kubectl get services -n NAMESPACE
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-console-mariadb ClusterIP 10.105.216.25 <none> 3306/TCP 60s
my-console-ui-ext NodePort 10.109.207.70 <none> 443:31067/TCP 60s

In this example, Stratos has been deployed withe the service configured as NodePort.

The URL you use for accessing Stratos will depend on the service configuration and the environment that you have used.

Note: If you did not provide a certificate when installing, Stratos will use a self-signed certificate, so you will see a certificate warning which you access Stratos in a browser.

Upgrading your deployment

To upgrade your instance when using the Helm repository, fetch any updates to the repository:

helm repo update

To update an instance, the following assumes your instance is called my-console:

helm upgrade my-console stratos/console

After the upgrade, perform a helm list to ensure your console is the latest version.

Uninstalling

To uninstall Stratos, delete the Helm release and also delete the Kubernetes namespace:

helm delete my-console --purge
kubectl delete namespace console

Note: Stratos creates secrets in the namespace as part of an initialization job. These are not managed by Helm, so make sure you +delete the namespace to remove these secrets.

Advanced Topics

Using a Load Balancer

If your Kubernetes deployment supports automatic configuration of a load balancer (e.g. Google Container Engine), specify the parameters console.service.type=LoadBalancer when installing.

kubectl create namespace console
helm install my-console stratos/console --namespace=console --set console.service.type=LoadBalancer

Using an Ingress Controller

If your Kubernetes Cluster supports Ingress, you can expose Stratos through Ingress by supplying the appropriate ingress configuration when installing.

This configuration is described below:

ParameterDescriptionDefault
console.service.ingress.enabledEnables ingressfalse
console.service.ingress.annotationsAnnotations to be added to the ingress resource.{}
console.service.ingress.extraLabelsAdditional labels to be added to the ingress resource.{}
console.service.ingress.hostThe host name that will be used for the Stratos service.
console.service.ingress.secretNameThe existing TLS secret that contains the certificate for ingress.

You must provide console.service.ingress.host when enabling ingress.

By default a certificate will be generated for TLS. You can provide your own certificate by creating a secret and specifying this with console.service.ingress.secretName.

Note: If you do not supply console.service.ingress.host but do supply env.DOMAIN then the host console.[env.DOMAIN] will be used.

Deploying from a Private Image Repository

If the images used by the chart are hosted in a private repository, the following needs to be specified. Save the following to a file called private_overrides.yaml. Replace REGISTRY USER PASSSWORD, REGISTRY USERNAME, REGISTRY URL with the appropriate values. USER EMAIL can be left blank.

kube:
registry:
password: <REGISTRY USER PASSWORD>
username: <REGISTRY USERNAME>
hostname: <REGISTRY URL>
email: <USER EMAIL or leave blank>

Deploy with:

kubectl create namespace console
helm install my-console stratos/console --namespace=console -f private_overrides.yaml

Deploying with your own TLS certificates

By default the console will generate self-signed certificates for demo purposes. To configure Stratos to use your provided TLS certificate, create a TLS secret in the namespace you are installing into and specify this secret name using the helm chart value console.tlsSecretName when installing.

Assuming you have your certificate and key in the files tls.crt and tls.key, create the secret with:

kubectl create secret tls -n NAMESPACE stratos-tls-secret --cert=tls.crt --key=tls.key

Where NAMESPACE is the namespace you are installing Stratos into - you will need to manually create the namespace first if it does not already exist.

You can now install Stratos with:

kubectl create namespace console
helm install my-console stratos/console --namespace=console --set console.tlsSecretName=stratos-tls-secret
+

Using an External Database

You can choose to use Stratos with an external database, rather than deploying a single-node MariaDB instance as part of the Helm install.

To do so, specify console.mariabdb.external=true when deploying.

You will also need to specify:

  • console.mariadb.host as the hostname of the external MariaDB database server
  • console.mariadb.port as the port of the external MariaDB database server (defaults to 3306)
  • console.mariadb.tls as the TLS mode (default is false, use true for a TLS connection to the database server)
  • console.mariadb.database as the name of the database
  • console.mariadb.user as the username to connect to the database server
  • console.mariadb.userPassword as the password to connect to the database server

When using an external database server, Stratos expects that you have:

  • Created a user that will be used to access the database
  • Created a database for the Stratos tables and data
  • Granted appropriate permissions so that the user can access the database

Note: When using a database from a Cloud provider, ensure that the username is correct - in some cases this will be username@servername - check the provided connection documentation

Specifying UAA configuration

When deploying with SCF, the scf-config-values.yaml (see SCF Wiki link) can be supplied when installing Stratos.

kubectl create namespace console
helm install my-console stratos/console --namespace=console -f scf-config-values.yaml

UAA configuration can be specified by providing the following configuration.

Create a yaml file with the content below and and update according to your environment and save to a file called uaa-config.yaml.

uaa:
endpoint: https://uaa.cf-dev.io:2793
consoleClient: cf
consoleClientSecret:
consoleAdminIdentifier: cloud_controller.admin
skipSSLValidation: false

To install Stratos with the above specified configuration:

kubectl create namespace console
helm install my-console stratos/console --namespace=console -f uaa-config.yaml

Configuring a local user account

This allows for deployment without a UAA. To enable the local user account, supply a password for the local user in the deployment command, as follows. All other steps for each deployment method should be followed as in the preceding sections above.

To deploy using our Helm repository:

kubectl create namespace console
helm install my-console stratos/console --namespace=console --set console.localAdminPassword=<password>

Specifying Annotations and Labels

In some scenarios it is useful to be able to add custom annotations and/or labels to the Kubernetes resources that the Stratos Helm chart creates.

The Stratos Helm chart exposes a number of Helm chart values that cabe specified in order to do this - they are:

ParameterDescriptionDefault
console.podAnnotationsAnnotations to be added to all pod resources
console.podExtraLabelsAdditional labels to be added to all pod resources
console.statefulSetAnnotationsAnnotations to be added to all statefulset resources
console.statefulSetExtraLabelsAdditional labels to be added to all statefulset resources
console.deploymentAnnotationsAnnotations to be added to all deployment resources
console.deploymentExtraLabelsAdditional labels to be added to all deployment resources
console.jobAnnotationsAnnotations to be added to all job resources
console.jobExtraLabelsAdditional labels to be added to all job resources
console.service.annotationsAnnotations to be added to all service resources
console.service.extraLabelsAdditional labels to be added to all service resources
console.service.ingress.annotationsAnnotations to be added to the ingress resource
console.service.ingress.extraLabelsAdditional labels to be added to the ingress resource

Requirements

Storage Class

Stratos uses persistent volumes. In order to deploy it in your Kubernetes environment, you must +have a storage class available.

Without configuration, the Stratos Helm Chart will use the default storage class. If a default storage +class is not available, installation will fail.

To check if a default storage class exists, you can list your configured storage classes with kubectl get storageclass. If no storage class has (default) after it, then you need to either specify a storage class override or declare a default storage class for your Kubernetes cluster.

For non-production environments, you may want to use the hostpath storage class. See the SCF instructions for details on setting this up. Note that you will need to make this storage class the default storage class, e.g.

kubectl patch storageclass <your-class-name> -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

Where <your-class-name> would be hostpath if you follow the SCF instructions.

Specifying a custom Storage Class

If no default storage class has been defined in the Kubernetes cluster. The Stratos helm chart will fail to deploy successfully. To check if a default storage class exists, you can list your configured storage classes with kubectl. If no storage class has (default) after it, then you need to either specify a storage class override or declare a default storage class for your Kubernetes cluster.

Providing Storage Class override

kubectl get storageclass
NAME TYPE
ssd kubernetes.io/host-path
persistent kubernetes.io/host-path

For instance to use the storage class persistent to deploy Console persistent volume claims, store the following to a file called override.yaml.

---
storageClass: persistent

If you want MariaDB to use a specific storage class (which can be different to that used for the other components), then specify the following:

---
storageClass: persistent
mariadb:
persistence:
storageClass: persistent

Run Helm with the override:

kubectl create namespace console
helm install my-console stratos/console --namespace=console -f override.yaml

Create a default Storage Class

Alternatively, you can configure a storage class with storageclass.kubernetes.io/is-default-class set to true. For instance the following storage class will be declared as the default. If you don't have the hostpath provisioner available in your local cluster, please follow the instructions on link, to deploy one.

If the hostpath provisioner is available, save the file to storageclass.yaml

---
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
name: default
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/host-path # Or whatever the local hostpath provisioner is called

To create it in your kubernetes cluster, execute the following.

kubectl create -f storageclass.yaml

See Storage Class documentation for more information.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/deploy/kubernetes/index.html b/website/site-dist/docs/deploy/kubernetes/index.html new file mode 100644 index 0000000000..f47fec338b --- /dev/null +++ b/website/site-dist/docs/deploy/kubernetes/index.html @@ -0,0 +1,33 @@ + + + + + + +Deploying in Kubernetes | STRATOS + + + + + + + + + + + + +
+

Deploying in Kubernetes

Stratos can be deployed to Kubernetes using Helm.

As part of the Stratos release process, a Helm chart is generated and added to the release artifacts for a given release. In addition, we maintain a Helm Chart repository that can be used to install Stratos from:

https://cloudfoundry.github.io/stratos

You will need a suitable Kubernetes environment and a machine from which to run the deployment commands.

You will need to have both the kubectl and helm CLIs installed and available on your path. It should be appropriately configured to be able to communicate with your Kubernetes environment.

The Stratos Helm chart contains a README.md file that contains installation instructions and configuration documentation.

This document is also available in here.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/deploy/troubleshooting/index.html b/website/site-dist/docs/deploy/troubleshooting/index.html new file mode 100644 index 0000000000..831f54f243 --- /dev/null +++ b/website/site-dist/docs/deploy/troubleshooting/index.html @@ -0,0 +1,36 @@ + + + + + + +General Troubleshooting | STRATOS + + + + + + + + + + + + +
+

General Troubleshooting

Deploying as a Cloud Foundry Application

See the custom troubleshooting guide here.

Usernames appear as long random characters when connected to IBM Cloud

Problem

Connecting to an IBM Cloud with the address https://api.<custom region>.bluemix.net avoids a proxy, https://mccp.<custom region>.bluemix.net, +that IBM tools use to flesh out users with their username. This results in a missing username field, which we fill with the user's guid +instead.

Solution

Unregister the IBM Cloud endpoint that contains the address https://api.<custom region>.bluemix.net and register again with the address +https://mccp.<custom region>.bluemix.net

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/developer/backend/index.html b/website/site-dist/docs/developer/backend/index.html new file mode 100644 index 0000000000..15661acb41 --- /dev/null +++ b/website/site-dist/docs/developer/backend/index.html @@ -0,0 +1,40 @@ + + + + + + +Backend Development | STRATOS + + + + + + + + + + + + +
+

Backend Development

Backend Development

Jetstream is the back-end for Stratos. It is written in Go.

We use Go Modules for dependency management.

Pre-requisites

You will need the following installed/available:

  • go 1.12 or later.

*For authentication, either*

  • A UAA instance
  • A local user account

Building the back-end

Build

From the src/jetstream folder, build the Stratos back-end with:

npm run build-backend

The back-end executable is named jetstream and should be created within the src/jetstream folder.

Configuration

Configuration can either be done via

  • Environment Variable and/or Config File
  • In the UI when you first use a front end with this backend

In all cases the configuration is saved to the database on first run. Any subsequent changes require the db to be reset. For the default sqlite +db provider this can be done by deleting src/jetstream/console-database.db

Configure by Environment Variables and/or Config File

By default, the configuration in file src/jetstream/default.config.properties will be used. These can be changed by environment variables +or an overrides file.

Environment variable

If you wish to use a local user account, ensure you have set the following environment variables:

  • AUTH_ENDPOINT_TYPE=local
  • LOCAL_USER - The username for the local user
  • LOCAL_USER_PASSWORD - The password for the local user
  • LOCAL_USER_SCOPE=stratos.admin - This gives the local user admin permissions. Currently other roles are not available.

If you have a custom uaa, ensure you have set the following environment variables:

  • UAA_ENDPOINT- the URL of your UAA
    • If you have an existing CF and want to use the same UAA use the authorization_endpoint value from [cf url]/v2/info +For example for PCF Dev, use: UAA_ENDPOINT=https://login.local.pcfdev.io.
  • CONSOLE_CLIENT - the Client ID to use when authenticating against your UAA (defaults to: 'cf')
  • CONSOLE_CLIENT_SECRET - the Client ID to use when authenticating against your UAA (defaults to empty)
  • CONSOLE_ADMIN_SCOPE - an existing UAA scope that will be used to identify users as Stratos Admins

To use a pre-built Stratos UAA container execute docker run --name=uaa --rm -p 8080:8080 -P splatform/stratos-uaa. The UAA will be +available at http://localhost:8080 with a CONSOLE_CLIENT value of console

Config File

To easily persist configuration settings copy src/jetstream/default.config.properties to src/jetstream/config.properties. The backend will load its +configuration from this file in preference to the default config file, if it exists. You can also modify individual configuration settings +by setting the corresponding environment variable.

To configure a local user account via config file

In src/jetstream/config.properties uncomment the following lines:

AUTH_ENDPOINT_TYPE=local
LOCAL_USER=localuser
LOCAL_USER_PASSWORD=localuserpass
LOCAL_USER_SCOPE=stratos.admin

Load the Stratos UI and proceed to log in using the configured credentials.

To configure UAA via Stratos

  1. Go through the Config File step above and comment out the UAA_ENDPOINT with a # in the new config.properties file.
  2. If any previous configuration attempt has been made reset your database as described above.
  3. Continue these steps from Run.
    • You should see the line Will add setup route and middleware in the logs
  4. Load the Stratos UI as usual and you should be immediately directed to the setup wizard

The setup wizard that allows you to enter the values normally fetched from environment variables or files. The UI will assist you through +this process, validating that the UAA address and credentials are correct. It will also provide a list of possible scopes for the Stratos Admin

Run

Execute the following file from src/jetstream

jetstream

You should see the log as the backend starts up. You can press CTRL+C to stop the backend.

Automatically register and connect to an existing endpoint

To automatically register a Cloud Foundry add the environment variable/config setting below:

AUTO_REG_CF_URL=<api url of cf>

Jetstream will then attempt to auto-connect to it with the credentials supplied when logging into Stratos.

Running Jetstream in a container

We recommend running Stratos using the Docker All-In-One image.

  • Follow instructions in the deploy/all-in-one docs
+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/developer/developers-guide-e2e-tests/index.html b/website/site-dist/docs/developer/developers-guide-e2e-tests/index.html new file mode 100644 index 0000000000..aaefc5eb34 --- /dev/null +++ b/website/site-dist/docs/developer/developers-guide-e2e-tests/index.html @@ -0,0 +1,35 @@ + + + + + + +E2E Tests | STRATOS + + + + + + + + + + + + +
+

E2E Tests

The Stratos E2E test suite exercises the Stratos UI using protractor/web-driver.

The tests require a Stratos instance to be running (front-end and back-end) and for a Cloud Foundry to be available to use for testing.

Developers' should be aware that:

  • The E2E tests are destructive on the Stratos system being tested - since they test endpoint registration, they will un-register any existing endpoints
  • The E2E tests will create orgs, spaces, applications, routes, etc in the Cloud Foundry instance that is specified. Tests should automatically tidy up afterwards unless stopped abruptly.

Pre-requisites

NPM

The test run via NPM, which should be installed the normal way.

Cloud Foundry

The tests require an instance of Cloud Foundry with the following:

  • A user with cloud-controller.admin scope (i.e. an Cloud Foundry admin)
  • A user without cloud-controller.admin scope (i.e. a regular Cloud Foundry user)
  • A user which both scim.invite and cloud_controller.admin (i.e. a Cloud Foundry user that can use the invite user feature)
  • A number of pre-existing orgs, spaces with appropriate roles applied to the admin and non-admin users
  • A number of other Cloud Foundry entities

To meet the above requirements we recommend running the Stratos CF E2E set up script which is kept up to date with the latest test requirements. +More information can be found below

Before running the E2E tests, you need to create a file named secrets.yaml in the root of the Stratos folder. An example template is included in src/test-e2e/secrets.yaml.example - copy this to secrets.yaml and edit accordingly.

If you want to run the tests in headless Chrome, add the following to the secrets file:

headless: true

Running the E2E Set up Script

The script can be found in deploy/tools/init-cf-for-e2e.sh

Minimum Requirements

  • CF CLI
  • UAA CLI
  • A user with cloud-controller.admin scope (i.e. an Cloud Foundry admin)

Script Output

The script does a number of things, including but not exclusively...

  • Creates test CF users
  • Creates an organisation and space to test a subset of features in, including assigning roles to certain configured users
  • Clones a basic CF application from github and pushes to the test org/space
  • Creates a new user in uaa which will be used to configure the Invite User feature
  • Enables deploying applications from docker
  • Creates a number of public, private and space scoped services from applications it pushes to CF

Running the Script

Please see the file itself for a list of required properties. Some have defaults in. We would recommend updating at least

  • ADMIN - Username for the CF admin
  • ADMIN_PASS - Password for the CF admin
  • CF_API_ENDPOINT - CF to test against
  • UAA_CLI_CMD - UAA CLI command
  • UAA_ENDPOINT - UAA endpoint used by CF
  • ADMIN_CLIENT_SECRET - UAA admin client's secret
  • UAA_ZONE - Leave blank if no zone is required

Configure Tests To Use Script Output

Given the output of the script, the following template can be used to update the CF section of secrets.yaml

cf:
- name: cf
url: <CF_URL>
skipSSLValidation: true
testOrg: e2e
testSpace: e2e
testService: app-autoscaler
services:
bindApp: go-env
publicService:
name: public-service
privateService:
name: private-service
invalidOrgName: test-e2e
invalidSpaceName: test-e2e
spaceScopedService:
name: space-scoped-service
invalidOrgName: test-e2e
invalidSpaceName: test-e2e
creds:
admin:
username: <CF_ADMIN_USERNAME>
password: <CF_ADMIN_PASSWORD>
nonAdmin:
username: e2e
password: changeme
removeUser:
username: e2e-remove-user
password: changeme
invite:
clientId: stratos-invite
clientSecret: changeme
uaa:
creds:
clientId: <uaa client id>
clientSecret: <uaa client secret>
tokenEndpoint: <uaa endpoint>
zone: <uaa zone>

Tidying up test generated CF entities

If tests are stopped before completing or fail to clean old test artifacts will exist in the CF. To clean some of these please see the script +at deploy/ci/automation/e2e-clean-remnants.sh

Running the tests

To run the tests against an instance of Stratos execute

npm run e2e -- --dev-server-target= --base-url=<URL of stratos

Running tests on Browserstack

You can run the E2E tests on Browserstack instead of with a local browser.

To do so, configure the following environment variables:

VariableRequiredDescription
BROWSERSTACK_USERYesYour Browserstack user ID
BROWSERSTACK_KEYYesYour Browserstack key
BROWSERSTACK_TARGETYesThe Browser (and OS) to use (see below)
BROWSERSTACK_PROJECTNoProject name
BROWSERSTACK_BUILDNoBuild name
BROWSERSTACK_NAMENoName
BROWSERSTACK_RESOLUTIONNoScreen resolution to use

For more information on project, build and name, see: https://www.browserstack.com/automate/capabilities.

The BROWSERSTACK_TARGET environment variable can be just a Browser name, e.g. Chrome, or a name and version (separated by a space), e.g. Chrome 69.

You can also specify which OS to use by separating the OS and browser with a /, e.g. Windows/Chrome. You can also specify the OS version by separating with a space, e.g. Windows 10/Chrome. You can fully described the OS and Browser with Windows 10/Chrome 69.

For more information on supported Operating Systems/devices and browsers, see https://www.browserstack.com/list-of-browsers-and-platforms?product=js_testing and https://www.browserstack.com/automate/protractor.

As an example, to run the E2E tests against a locally run Stratos dev system, use:

BROWSERSTACK_TARGET="Chrome" npm run e2e-dev

Note: This assumes you have set the BROWSERSTACK_USER and BROWSERSTACK_KEY environment variables already.

Running the tests in this manner uses the browserstack-local npm package to allow the tests to run against your local system. To ensure that BrowserStackLocal processes are not left running if a test run is aborted, all BrowserStackLocal processes are terminated when the E2E test process exits.

Note: When the E2E tests are run using BrowserStack, the test reporter is modified to include timing information to help correlate tests to the captured video of the test run.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/developer/developers-guide-env-tech/index.html b/website/site-dist/docs/developer/developers-guide-env-tech/index.html new file mode 100644 index 0000000000..633b0123c1 --- /dev/null +++ b/website/site-dist/docs/developer/developers-guide-env-tech/index.html @@ -0,0 +1,33 @@ + + + + + + +Stratos Tech + Developer Environment | STRATOS + + + + + + + + + + + + +
+

Stratos Tech + Developer Environment

ES6

TypeScript

Angular

Angular

Angular CLI

Example Apps

Redux

Observables

VS Code Plug-ins

There's no mandated IDE, but if you choose VS Code here's some helpful plug-ins

Super Helpful

  • TSLint
  • SassLint
  • TS Hero
  • Beautify
  • gitignore

Helpful

  • Angular 2+ Snippets

  • Angular v4 TypeScript Snippets

  • Git Lens

  • Document This

  • Git History

  • TODO Parser

    • see icon bottom left for todo's in current file

    • Add the following config to settings to exclude some folders

      "TodoParser": {
      "folderExclude": ["node_modules", ".vscode"]
      }
    • F1 + Parse TODOs (all files) to see all TODOs

  • Move TS - Move files and automatically update imports

Of Interest

  • Eclipse Keymap
  • Code Spell Checker
    • List of words to exclude coming soon

Example settings

{
"gitlens.blame.line.enabled": false,
"gitlens.codeLens.recentChange.enabled": false,
"gitlens.codeLens.authors.enabled": false,
"gitlens.blame.highlight.locations": [
"gutter",
"overview"
],
"gitlens.currentLine.enabled": false,
"gitlens.hovers.currentLine.enabled": false,
"editor.fontSize": 12,
"editor.formatOnSave": true,
"editor.rulers": [
140
],
"editor.renderLineHighlight": "none",
"search.exclude": {
"node_modules": true,
"**/node_modules": true,
"**/bower_components": true,
"coverage": true,
"components/*/backend/vendor": true,
"*.orig": true
},
"search.useIgnoreFilesByDefault": true,
"tslint.validateWithDefaultConfig": true,
"tslint.configFile": "tslint.json",
"tslint.autoFixOnSave": true,
"tslint.alwaysShowStatus": true,
"tslint.alwaysShowRuleFailuresAsWarnings": true,
"explorer.autoReveal": false,
"extensions.ignoreRecommendations": false,
"TodoParser": {
"folderExclude": [
"node_modules",
".vscode"
]
},
"cSpell.userWords": [
"Guids",
"action",
"api",
"cnsi",
"cnsis",
"confirmation",
"dialog",
"falsies",
"guid",
"iapi",
"initialise",
"initialised",
"injectable",
"memberof",
"ngrx",
"normalizr",
"strat",
"unsubscribe",
"vars"
],
"cSpell.language": ",en-GB",
"cSpell.enabledLanguageIds": [
"c",
"css",
"cpp",
"csharp",
"fonts",
"go",
"handlebars",
"javascript",
"javascriptreact",
"json",
"latex",
"markdown",
"php",
"plaintext",
"python",
"restructuredtext",
"text",
"typescript",
"typescriptreact",
"yml",
"html"
],
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"**/tmp": true,
"**/node_modules": true,
"**/bower_components": true,
"**/dist": true,
"**/.orig": true
},
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/node_modules/**": true,
"**/tmp/**": true,
"**/bower_components/**": true,
"**/dist/**": true
},
}

Guides

ExpressionChangedAfterItHasBeenCheckedError Error

Links

In summary

  • AVOID
    • setTimeout
    • forcing change detecting
  • TRY TO USE
    • observeOn(asapScheduler) in observable chain
    • ngAfterViewInit
  • Generally
    • Avoid changing state in child components that will affect a binding in parent component/s
+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/developer/frontend-tests/index.html b/website/site-dist/docs/developer/frontend-tests/index.html new file mode 100644 index 0000000000..1fdb7485de --- /dev/null +++ b/website/site-dist/docs/developer/frontend-tests/index.html @@ -0,0 +1,37 @@ + + + + + + +Frontend Tests | STRATOS + + + + + + + + + + + + +
+

Frontend Tests

Test

Lint

Run npm run lint to execute tslint lint checking.

Unit tests

Run npm test to execute the unit tests via Karma. Coverage information can be found in ./coverage

To execute an individual package run ng test <package name>. To execute the tests again automatically on code changes add --watch=true

NOTE npm test will search for chrome on your path. If this is not so please set an env var CHROME_BIN pointing to your executable +(chromium is fine too).

End-to-end tests

Run npm run e2e to execute the end-to-end tests via Protractor.

Run npm run e2e-dev to execute end-to-end tests against a locally running instance on https://localhost:4200

More information on the E2E tests and pre-requisites for running them is available here - E2E Tests.

Code Climate

We use Code Climate to check for general code quality issues. This executes against Pull +Requests on creation/push.

Running Code Climate locally

Generally we would not advise doing this and just rely on the code climate gate to run when pull requests are submitted

To run locally see instructions here to install Code Climate CLI +and engine via docker. Once set ensure you're in the root of the project and execute the following (it may take a while)

codeclimate analyze

NOTE Unfortunately this highlights all current issues and not those that are the diff between any master and feature branch. Analyze +can be ran against a single/sub set of files, again with all current issues, but a little more digestible.

codeclimate analyze <path to file/s>

In a feature branch to compare files that have changed to master, for instance, use the following

git checkout feature-branch-A
codeclimate analyze $(git diff --name-only master)

You can also run the above command via npm

npm run climate

Stratos Continue Integration

For each new pull request and any subsequent pushes to it the following actions are executed

  • Code quality analysis via Code Climate - https://codeclimate.com/
  • Jenkins CI run, covering..
    • Frontend lint check
    • Backend lint check
    • Frontend unit tests
    • Backend unit tests
    • End to end tests
  • Security anaylsis via Snyk - https://snyk.io/
+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/developer/frontend/index.html b/website/site-dist/docs/developer/frontend/index.html new file mode 100644 index 0000000000..7a63474834 --- /dev/null +++ b/website/site-dist/docs/developer/frontend/index.html @@ -0,0 +1,43 @@ + + + + + + +Frontend Development | STRATOS + + + + + + + + + + + + +
+

Frontend Development

Introduction to the stack

Have a look through the Env + Tech page to get acquainted with some of the new technologies used in v2. +These include video's, tutorials and examples of Angular 2+, Typescript and Redux. There's also some advice on helpful plugins to use if +using Visual Studio Code. If you feel comfortable with these and are happy with your dev environment please skip straight to +Set up Dependencies

Set up Dependencies

  • Set up a Stratos backend - The frontend cannot run without a backend. Both backend and frontend exist in this same repo.
    • Don't need to make changes to the backend code? To set up a backend run through the deploy section, +choose a deployment method and bring one up. These deployments will bring up the entire backend, including api service and database +along with a V2 frontend.
    • Need to make changes to the backend code? Follow the below Backend Development set up guide
  • Install NodeJs (minimum node version 12.13.0)
  • Install Angular CLI - npm install -g @angular/cli

Configuration

Configuration information can be found in two places

  • ./proxy.conf.js
    • In new forks this is missing and needs to be created using ./proxy.conf.template.js as a template.
    • Contains the address of the backend. Which will either be...
      • If the backend is deployed via the instructions in the deploy section +the url will be the same address as the V1 console's frontend address. For instance https://localhost would translate to
        const PROXY_CONFIG = {
        "/pp": {
        "target": {
        "host": "localhost",
        "protocol": "https:",
        "port": 443
        },
        "secure": false,
        "changeOrigin": true,
        "ws": true,
        }
      • If the backend is running locally using the instructions Backend Development below the url will local host +with a port of the CONSOLE_PROXY_TLS_ADDRESS value from src/jetstream/config.properties. By default this will be 5445. For +instance
        const PROXY_CONFIG = {
        "/pp": {
        "target": {
        "host": "localhost",
        "protocol": "https:",
        "port": 5443
        },
        "ws": true,
        "secure": false,
        "changeOrigin": true,
        }
        }
  • ./src/frontend/environments/environment.ts for developer vs production like config
    • This contains more general settings for the frontend and does not usually need to be changed

Run the frontend

  1. (First time only) Copy ./proxy.conf.template.js to ./proxy.conf.js and update with required Jetstream url (see above for more info)
  2. Run npm install
  3. Run npm start for a dev server. (the app will automatically reload if you change any of the source files)
    • If this times out please use npm run start-high-mem instead
    • To change the port from the default 4200, add -- --port [new port number]
    • To stop the automatic reload every time a resource changes add -- --live-reload false
    • To do both the above use -- --live-reload false --port [new port number]
  4. Navigate to https://localhost:4200/. The credentials to log in will be dependent on the Jetstream the console points at. Please refer +to the guides used when setting up the backend for more information

Build

Run npm run build to build the project.

The build artefacts will be stored in the dist/ directory. This will output a production build of the application.

Creating angular items via angular cli

To create a new angular component run ng generate component component-name. You can use a similar command to create other types of angular +items ng generate <directive|pipe|service|class|guard|interface|enum|module> <name>.

Theming

We use the angular material theming mechanism. See here for more information about theming new components added to stratos.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/developer/introduction/index.html b/website/site-dist/docs/developer/introduction/index.html new file mode 100644 index 0000000000..d34b0c07ab --- /dev/null +++ b/website/site-dist/docs/developer/introduction/index.html @@ -0,0 +1,33 @@ + + + + + + +Developing the Stratos Console | STRATOS + + + + + + + + + + + + +
+

Developing the Stratos Console

  1. Introduction
  2. Frontend Development
  3. Backend Development

Introduction

Stratos comprises of two main components:

  • A front-end UI that runs in your web browser. This is written in Typescript and uses the Angular framework.
  • A back-end that provides a web-based API to the front-end. This is written in Go.

Depending on what you are contributing, you will need to develop with the front-end, back-end or both.

Building and running the Frontend and Backend Locally

For a quick-start to get Stratos built and running locally on a development system, follow the steps below.

You will need to have go and nodejs installed in your development environment.

git clone https://github.com/cloudfoundry/stratos.git
cd stratos
npm install
npm run build
npm run build-backend
./src/jetstream/jetstream

This will build both the frontend and backend and run the backend in a mode where it will also serve the static resources for the frontend.

You can open a web browser and navigate to (https://127.0.0.1:5443) and login with username admin and password admin.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/extensions/backend/index.html b/website/site-dist/docs/extensions/backend/index.html new file mode 100644 index 0000000000..261a9a194e --- /dev/null +++ b/website/site-dist/docs/extensions/backend/index.html @@ -0,0 +1,33 @@ + + + + + + +Backend Plugins | STRATOS + + + + + + + + + + + + +
+

Backend Plugins

This document provides a brief outline for extending the Stratos backend (Jetstream).

Currently, to create an extension to the backend:

  1. Create a folder for your plugin, in the folder src/jetstream/plugins

  2. Edit src/jetstream/load_plugins.go and:

    • Add your plugin's package to the import block at the top of the file
    • Add your plugin to the list of plugins to be initialized in the loadPlugins function, e.g.
    {"myplugin", myplugin.Init},
  3. Build Jetstream

Note: There are a few plugins in the src/jetstream/plugins folder that should help serve as examples of how to write a plugin.

Note: Jetstream uses the Echo web server from Labstack - some familiarity with this is required when developing backend plugins.

Plugin Interface

All plugins must implement the interface interfaces.StratosPlugin - this is defined in src/jetstream/repository/interfaces/plugin.go.

A plugin can implement one or all of the following plugin interfaces - Middleware, Endpoint and Route.

This interface defines 4 functions:

  • Init() error - This is called to initialize the plugin. If an error is returned then the plugin will not be added to the backend.

  • GetMiddlewarePlugin() (MiddlewarePlugin, error) - Provides the middleware that this plugin wishes to add to Stratos, if any. Return an error if your plugin does not need to add middleware.

  • GetEndpointPlugin() (EndpointPlugin, error) - Provides the endpoint that this plugin wishes to add to Stratos, if any. Return an error if your plugin does not need to add middleware.

  • GetRoutePlugin() (RoutePlugin, error) - Provides the route that this plugin wishes to add to Stratos, if any. Return an error if your plugin does not need to add middleware.

Each of the three plugin interfaces are described below.

Middleware

The MiddlewarePlugin interface provides a plugin with a mechanism to add custom middleware to the Jetstream web server (Echo). This allows it to add upfront processing/filtering/handling of all API requests to the backend. There are two handlers that are required to be provided:

  • EchoMiddleware - This is added as middleware to the echo web server for all requests that are not guarded by the session gate - i.e. requests that a non-logged-in user can access

  • SessionEchoMiddleware - This is added as middleware to the echo web server for all requests that are guarded by the session gate - i.e. requests that only a logged-in user can access

This interface is defined in the file src/jetstream/repository/interfaces/general.go:

type MiddlewarePlugin interface {
EchoMiddleware(middleware echo.HandlerFunc) echo.HandlerFunc
SessionEchoMiddleware(middleware echo.HandlerFunc) echo.HandlerFunc
}

Endpoint

The EndpointPlugin should be used when a plugin wishes to add a new type of Endpoint. An example of this is the Metrics plugin in the folder src/jetstream/plugins/metrics.

This interface is defined in the file src/jetstream/repository/interfaces/endpoints.go:

type EndpointPlugin interface {
Info(apiEndpoint string, skipSSLValidation bool) (CNSIRecord, interface{}, error)
GetType() string
Register(echoContext echo.Context) error
Connect(echoContext echo.Context, cnsiRecord CNSIRecord, userId string) (*TokenRecord, bool, error)
UpdateMetadata(info *Info, userGUID string, echoContext echo.Context)
}

Adding a new Endpoint type is more involved than other plugin types and will be documented in more detail later.

For now, briefly:

  • GetType is used to return the endpoint type - a unique ID for the endpoint type - e.g. "metrics"
  • Info is used to obtain information for the given endpoint URL
  • Register is called when the user wants to register a new Endpoint of this type
  • Connect is called when the user wants to connect a new Endpoint of this type
  • UpdateMetadata is called when the info request is made to the backend and gives each endpoint plugin the opportunity to update the metadata returned. For example, in the case of metrics, the plugin will update endpoints to indicate which have metrics metadata available.

Routes

The RoutePlugin interface provides a plugin with a mechanism to add custom handlers to the Jetstream web server (Echo). This allows it to add any custom API processing. There are two handlers that are required to be provided:

  • AddSessionGroupRoutes - This is added as a handler to the echo web server and is guarded so that only logged-in users can access.

  • AddAdminGroupRoutes - This is added as a handler to the echo web server and is guarded so that only logged-in users who are Stratos Administrators can access.

This interface is defined in the file src/jetstream/repository/interfaces/endpoints.go:

type RoutePlugin interface {
AddSessionGroupRoutes(echoContext *echo.Group)
AddAdminGroupRoutes(echoContext *echo.Group)
}

The primary purpose of the RoutePlugin is to add new APIs to Jetstream.

All handlers are added under the /v1 URL prefix.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/extensions/frontend/index.html b/website/site-dist/docs/extensions/frontend/index.html new file mode 100644 index 0000000000..59f906414c --- /dev/null +++ b/website/site-dist/docs/extensions/frontend/index.html @@ -0,0 +1,40 @@ + + + + + + +Frontend Extensions | STRATOS + + + + + + + + + + + + +
+

Frontend Extensions

An example illustrating the various front-end extension points of Stratos is included in the folder examples/custom-src.

To include the customizations in this example, either copy or symlink the examples/custom-src to custom-src at the top-level of the Stratos repository.

Next, run the customization script (this is done automatically when you do an npm install) with:

npm run customize

You can now run Stratos locally to see the customizations - see the Developer's Guide for details.

For a walk-through of extending Stratos, see Example: Adding a Custom Tab.

Extension Points

Side Navigation

New items can be added to the Side Navigation menu with extensions.

To do so, annotate the routes for your extension with custom metadata, which Stratos will then pick up and add to the side menu.

A full example is in the folder examples/custom-src/frontend/app/custom/nav-extension.

Your route should have the following metadata in the data field:

stratosNavigation: {
text: '<TITLE>',
matIcon: '<ICON NAME>'
}

Where <TITLE> is the text label to show in the side navigation and <ICON NAME> is the icon to use.

You should place your route declaration in a module named CustomRoutingModule in the file custom-src/frontend/app/custom/custom-routing.module.ts.

An example routing module would be:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
+
const customRoutes: Routes = [{
path: 'example',
loadChildren: 'app/custom/nav-extension/nav-extension.module#NavExtensionModule',
data: {
stratosNavigation: {
text: 'Example',
matIcon: 'extension'
}
}
}];
+
@NgModule({
imports: [
RouterModule.forRoot(customRoutes),
],
declarations: []
})
export class CustomRoutingModule { }

This approach ensures that the Angular compiler creates a separate chunk for the extension at compile time.

Custom Tabs

Tabs can be added to the following views in Stratos:

  • The Application view that shows the detail of an application
  • The Cloud Foundry view that shows detail for a Cloud Foundry
  • The Cloud Foundry Org view that shows detail for a Cloud Foundry organization
  • The Cloud Foundry Space view that shows detail for a Cloud Foundry space

For example:

Example Application tab extension

The approach for all of these is the same:

  1. Create a new component that will provide the tab contents
  2. Ensure that your component is included in the EntryComponent section of your custom module
  3. Decorate the component with the StratosTab decorator, for example:
@StratosTab({
type: StratosTabType.Application,
label: '<LABEL>',
link: '<LINK>'
})

Where:

  • < TYPE > indicates where the tab should appear and can be:
    • StratosTabType.Application - Application View
    • StratosTabType.CloudFoundry - Cloud Foundry view
    • StratosTabType.CloudFoundryOrg - Cloud Foundry Org view
    • StratosTabType.CloudFoundrySpace - Cloud Foundry Space view
  • < LABEL > is the text label to use for the tab
  • < LINK > is the name to use for the route (this must only contain characters permitted in URLs)

An example is included in the file examples/custom-src/frontend/app/custom/app-tab-extension.

Custom Actions

Actions can be added to the following views in Stratos:

  • The Application Wall view that shows all applications
  • The Application view that shows the detail of an application
  • The Cloud Foundry view that shows detail for a Cloud Foundry
  • The Cloud Foundry Org view that shows detail for a Cloud Foundry organization
  • The Cloud Foundry Space view that shows detail for a Cloud Foundry space
  • The Endpoints view that shows all endpoints

An action is a icon button that appears at the top-right of a View. For example:

Example Application action extension

The approach for all of these is the same:

  1. Create a new component that will provide the contents to show when the action is clicked
  2. Ensure that your component is included in the EntryComponent section of your custom module
  3. Decorate the component with the StratosAction decorator, for example:
@StratosAction({
type: StratosActionType.Applications,
label: '<LABEL>',
link: '<LINK>',
icon: '<ICON>
})

Where:

  • < TYPE > indicates where the action should appear and can be:
    • StratosActionType.Applications - Application Wall View
    • StratosActionType.Application - Application View
    • StratosActionType.CloudFoundry - Cloud Foundry view
    • StratosActionType.CloudFoundryOrg - Cloud Foundry Org view
    • StratosActionType.CloudFoundrySpace - Cloud Foundry Space view
    • StratosActionType.Endpoints - Endpoints view
  • < ICON > is the icon to show
  • < LABEL > is the text label to use for the tooltip of the icon (optional)
  • < LINK > is the name to use for the route (this must only contain characters permitted in URLs)

An example is included in the file examples/custom-src/frontend/app/custom/app-action-extension.

Example: Adding a Custom Tab

In this example, we will walk through extending the Stratos front-end.

This walk-through assumes that you have installed the Angular CLI globally - this can be done with npm install -g @angular/cli.

Create a new module

First, create the custom-src folder structure - from the top-level of the Stratos repository run:

mkdir -p custom-src/frontend/app/custom
mkdir -p custom-src/frontend/assets/custom

Next, run the customize task:

npm run customize

This will symlink our custom folder into the Stratos application source folder.

Next, use the Angular CLI to create the root module for our custom code with:

ng generate module custom

This create a new Angular module CustomModule.

Run the customize script again, now that that we have created the custom module with:

npm run customize

Create a new Component for our Tab

Create a new Angular component with the CLI:

ng generate component custom/example-tab-extension

Add Decorator to make this Component an Extension

In a text editor, open the file:

src/frontend/app/custom/example-tab-extension/example-tab-extension.component.ts

Add the following decorator to the component at the top of the file:

import { StratosTab, StratosTabType } from '../../core/extension/extension-service';
+
@StratosTab({
type: StratosTabType.Application,
label: 'Example App Tab',
link: 'example'
})

The file should now look like this:

import { Component, OnInit } from '@angular/core';
import { StratosTab, StratosTabType } from '../../core/extension/extension-service';
+
@StratosTab({
type: StratosTabType.Application,
label: 'Example App Tab',
link: 'example'
})
@Component({
selector: 'app-example-tab-extension',
templateUrl: './example-tab-extension.component.html',
styleUrls: ['./example-tab-extension.component.scss']
})
export class ExampleTabExtensionComponent implements OnInit {
+
constructor() { }
+
ngOnInit() {
}
+
}

Save the file.

Mark the component as an entry component

The last thing we need to do is to mark our Extension component as an entry component.

To do this, in a text editor, open the file src/frontend/app/custom/custom.module.ts and add the entry components section so it looks like this:

@NgModule({
imports: [
CommonModule
],
declarations: [ExampleTabExtensionComponent],
entryComponents: [ExampleTabExtensionComponent]
})
export class CustomModule { }

Run it

You should now be able to run Stratos locally and see this new tab on the application page for an application - as illustrated below:

Example tab extension

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/extensions/introduction/index.html b/website/site-dist/docs/extensions/introduction/index.html new file mode 100644 index 0000000000..e6ea4b0757 --- /dev/null +++ b/website/site-dist/docs/extensions/introduction/index.html @@ -0,0 +1,33 @@ + + + + + + +Extending Stratos | STRATOS + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/extensions/theming/index.html b/website/site-dist/docs/extensions/theming/index.html new file mode 100644 index 0000000000..140ac218b6 --- /dev/null +++ b/website/site-dist/docs/extensions/theming/index.html @@ -0,0 +1,33 @@ + + + + + + +Theming Stratos | STRATOS + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/guides/contribution/contributing/index.html b/website/site-dist/docs/guides/contribution/contributing/index.html new file mode 100644 index 0000000000..9ca75607f9 --- /dev/null +++ b/website/site-dist/docs/guides/contribution/contributing/index.html @@ -0,0 +1,59 @@ + + + + + + +Contributing to Stratos | STRATOS + + + + + + + + + + + + +
+

Contributing to Stratos

Reporting issues

Before reporting an issue, please check whether it has already been reported +here. If this is the case, please:

  • Read all the comments to confirm that it's the same issue you're having.
  • Refrain from adding "same thing here" or "+1" comments. Just hit the +"subscribe" button to get notifications for this issue.
  • Add a comment only if you can provide helpful information that has not been +provided in the discussion yet.

If you want to report a new issue, please ensure you give as much detail +as possible about your setup/environment and provide sufficient steps +for the issue to be easily reproduced.

Check for assigned people

We use Github Issues for submitting known issues (e.g. bugs, features, +etc.). Some issues will have someone assigned, meaning that there's already +someone that takes responsibility for fixing the issue. This is not done to +discourage contributions, rather to not step in the work that has already been +done by the assignee. If you want to work on a known issue with someone already +assigned to it, please contact the assignee first (e.g. by +mentioning the assignee in a new comment on the specific issue). This way you +can contribute with ideas, or even with code if the assignee decides that you +can step in.

If you plan to work on a non assigned issue, please add a comment on the issue +to prevent duplicated work.

Sign your work

The sign-off is a simple line at the end of the explanation for the patch. Your +signature certifies that you wrote the patch or otherwise have the right to pass +it on as an open-source patch. The rules are pretty simple: if you can certify +the below (from developercertificate.org):

Developer Certificate of Origin
Version 1.1
+
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA
+
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
+
Developer's Certificate of Origin 1.1
+
By making a contribution to this project, I certify that:
+
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
+
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
+
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
+
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.

Then you just add a line to every git commit message:

Signed-off-by: Joe Smith <joe.smith@email.com>

Use your real name (sorry, no pseudonyms or anonymous contributions.)

If you set your user.name and user.email git configs, you can sign your +commit automatically with git commit -s.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/guides/contribution/issue_template/index.html b/website/site-dist/docs/guides/contribution/issue_template/index.html new file mode 100644 index 0000000000..604ab990cb --- /dev/null +++ b/website/site-dist/docs/guides/contribution/issue_template/index.html @@ -0,0 +1,33 @@ + + + + + + +Issue report template | STRATOS + + + + + + + + + + + + +
+

Issue report template

Frontend Deployment type

  • Cloud Foundry Application (cf push)
  • Kubernetes, using a helm chart
  • Docker, single container deploying all components
  • npm run start
  • Other (please specify below)

Backend (Jet Stream) Deployment type

  • Cloud Foundry Application (cf push)
  • Kubernetes, using a helm chart
  • Docker, single container deploying all components
  • Other (please specify below)

Expected behaviour

Actual behaviour

Steps to reproduce the behavior

Log output covering before error and any error statements

Insert log hereCopy

Detailed Description

Context

Possible Implementation

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/guides/contribution/pull_request_template/index.html b/website/site-dist/docs/guides/contribution/pull_request_template/index.html new file mode 100644 index 0000000000..e613c4ab8f --- /dev/null +++ b/website/site-dist/docs/guides/contribution/pull_request_template/index.html @@ -0,0 +1,33 @@ + + + + + + +Pull request template for contributions to Stratos | STRATOS + + + + + + + + + + + + +
+

Pull request template for contributions to Stratos

Description

Motivation and Context

How Has This Been Tested?

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Docs update
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have followed the guidelines in CONTRIBUTING.md, including the required formatting of the commit message
+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/guides/customization/customizing/index.html b/website/site-dist/docs/guides/customization/customizing/index.html new file mode 100644 index 0000000000..313bb01d2b --- /dev/null +++ b/website/site-dist/docs/guides/customization/customizing/index.html @@ -0,0 +1,47 @@ + + + + + + +Customizing Stratos | STRATOS + + + + + + + + + + + + +
+

Customizing Stratos

Stratos provides a mechanism for customization - the following customizations are currently supported:

  • Changing the theme colors
  • Changing certain image assets (favorite icon, login background and logo)
  • Overriding styles
  • Adding new functionality
  • Changing the initial loading indicator

Migrating to Stratos V4 Customization

In V4 there are breaking customization changes. These changes allow a much improved approach to extensions by opening the door to npm style plugins. +To aid in migrating we've provided these instructions.

1) Before updating to the latest code... +1) Run npm run customize-reset to remove all previously created sym links. +2) Read through the customization documentation below to get a better understanding of the new process. +1) Update your codebase with the desired v4 code. +1) Run npm install (only required first time, this will ensure you have the required version of Angular). +1) Change directory to ./build/tools/v4-migration and run the migration script ./migrate.sh.

- This will copy your customizations from `custom-src` to a new Angular package `src/frontend/packages/custom_extensions`.

1) Check that the new package exports your custom module and if applicable your custom-routing module.

- The migrate script should do this in `src/frontend/packages/custom_extensions/src/public-api.ts`.

1) Check that your ts config file defines the public api file.

- `src/tsconfig.json` file's `compilerOptions/paths` section should contain something like `"@custom/extensions": ["frontend/packages/custom_extensions/src/public-api.ts"]`.

1) Check that your new package's package.json defines your custom module and if application custom-routing module.

- See `src/frontend/packages/suse_extensions/package.json` file's `stratos` section.
- Note your `routingModule` entry label should not have a preceding `_`.

1) Build Stratos in your usual way, for instance npm run build.

- It could be that this fails due to TypeScript import issues, if so go through these and fix.
- During build time the custom packages will be discovered and output, see section starting `Building with these extensions`. These should contain the modules your require.

1) Run Stratos your usual way. Ensure you can navigate to all your custom parts. +1) Once you are happy everything works as intended remove the old ./custom-src directory and commit you changes.

Approach

In order to customize Stratos, you will need to fork the Stratos GitHub repository and apply customizations in your fork. Our aim is to minimize any merge conflicts that might occur when re-basing your fork with the upstream Stratos repository.

Customizations are placed in angular packages in the folder named src/frontend/packages. In the future you will be able to host these packages in npm and bring them into Stratos in the usual npm dependency way.

Each package should contain custom Stratos configuration in it's package.json pointing to the modules it will be required to import.

stratos.yaml +custom theme +custom styles +custom assets

The Stratos approach to customization uses symbolic links. We maintain a default set of resources in the folder src/misc/custom. When you run npm install or when you explicitly run npm run customize, a gulp task (in the file build/fe-build.js) runs and creates symbolic links, linking the required files to their expected locations withing the src folder.

If a required file exists in the custom-src folder location, the build script will link this file, otherwise, it will link the default resource from src/misc/custom.

Normally, you do not need to run any scripts to apply customizations - they will be applied as part of a postinstall script that runs automatically when you do an npm install. You can manually run the following scripts if you update or change the customizations:

  • npm run customize - creates symbolic links for the required files, looking at the provided customizations and then falling back to default files

  • npm run customize-default - creates symbolic links for the required files, ignoring any provided customizations and using the default files

  • npm run customize-reset - remove all symbolic links. If you build after running this command you will see errors, as required files are not present.

Customizing Images

The following image resources can be changed by creating the specified file in the folder shown:

File nameFolderDescription
favicon.icocustom-src/frontendFavorite icon to use
logo.pngcustom-src/frontend/assetsLogo to use on login screen and about page
nav-logo.pngcustom-src/frontend/assetsLogo to use in the top-left side navigation for the application logo
login-bg.jpgcustom-src/frontend/assetsImage to use for the login page background

NOTE: The nav-logo.png logo should have a height of 36px and a maximum width of 180 pixels.

Customizing the Theme

Stratos uses Material Design and the angular-material library. It uses the same approach to theming.

To create your own theme, create the file custom.scss in the folder custom-src/frontend/sass.

In this file you can set any or all of the following variables:

VariablePurpose
$stratos-themeThe main theme to use for Stratos
$stratos-nav-themeTheme to use for the side navigation panel
$stratos-status-themeTheme to use for displaying status in Stratos

Note that you do not have to specify all of these - defaults will be used if they are not set.

In most cases you will probably want to generate a palette for the primary color for your version of Stratos - an example custom.scss this for this is shown below:

$suse-green: ( 50: #E0F7F0, 100: #B3ECD9, 200: #80E0C0, 300: #4DD3A7, 400: #26C994, 500: #00C081, 600: #00BA79, 700: #00B26E, 800: #00AA64, 900: #009C51, A100: #C7FFE0, A200: #94FFC4, A400: #61FFA8, A700: #47FF9A, contrast: (50: #000000, 100: #000000, 200: #000000, 300: #000000, 400: #ffffff, 500: #ffffff, 600: #ffffff, 700: #ffffff, 800: #ffffff, 900: #ffffff, A100: #000000, A200: #000000, A400: #000000, A700: #000000 ));
+
$suse-red: ( 50: #ffebee, 100: #ffcdd2, 200: #ef9a9a, 300: #e57373, 400: #ef5350, 500: #f44336, 600: #e53935, 700: #d32f2f, 800: #c62828, 900: #b71c1c, A100: #ff8a80, A200: #ff5252, A400: #ff1744, A700: #d50000, contrast: ( 50: $black-87-opacity, 100: $black-87-opacity, 200: $black-87-opacity, 300: $black-87-opacity, 400: $black-87-opacity, 500: white, 600: white, 700: white, 800: $white-87-opacity, 900: $white-87-opacity, A100: $black-87-opacity, A200: white, A400: white, A700: white, ));
+
// Create palettes
$suse-app-primary: mat-palette($suse-green);
$suse-theme-warn: mat-palette($suse-red);
+
// Create a theme from the palette (secondary theme is the same as the primary in this example)
$suse-app-theme: mat-light-theme($suse-app-primary, $suse-app-primary, $suse-theme-warn);
+
// Set this theme as the one to use
$stratos-theme: $suse-app-theme;

Creating or disabling the Dark theme

You can also change the Dark theme, if you wish, by defining the following variables:

VariablePurpose
$stratos-dark-themeThe dark theme to use for Stratos
$stratos-dark-nav-themeDark theme to use for the side navigation panel
$stratos-dark-status-themeDark theme to use for displaying status in Stratos

Note that minimally you must supply stratos-dark-theme to create a dark theme.

By default a dark theme is assumed to be available and the default will be used if not overridden. You can disable dark theme support in the UI by setting the following variable in your custom.scss:

$stratos-dark-theme-supported: false;

Changing Styles

We don't generally recommend modifying styles, since from version to version of Stratos, we may change the styles used slightly which can mean any modifications you made will need updating. Should you wish to do so, you can modify these in the same custom.scss file that is used for theming.

As an example, to disable the login background image, add the following to custom.scss:

.stratos .intro {
background-image: none;
}

Note that the class stratos has been placed on the BODY tag of the Stratos application to assist with css selector specificity.

Adding new Features

Code for new features should be placed within the custom-src/frontend/app/custom folder. You can create any sub-folder structure within this folder.

When you perform an npm install or explicitly run npm run customize, the customize script is run and will symlink the folder custom-src/frontend/app/custom to src/frontend/app/custom. It will also create a module to import your custom code - this is placed in the file src/frontend/app/custom/custom-import.module.ts. You should not edit this file.

Within the custom-src/frontend/app/custom folder you must create a module in the file custom.module.ts named CustomModule - this will be imported into the Stratos application and is the mechanism by which you can add custom code to the front-end.

We currently expose the following extension points in the Stratos UI:

  • Changing the component to use for the login screen
  • Adding new items to the side navigation menu
  • Adding new tabs to the Application, Cloud Foundry, Organization and Space views
  • Adding new action buttons to the Application Wall, Application, Cloud Foundry, Organization and Space and Endpoint views

We use Decorators to annotate components to indicate that they are Stratos extensions.

See Extensions for more detail and examples of front-end extensions.

Changing the Initial Loading Indicator

On slower connections, it can take a few seconds to load the main Javascript resources for Stratos.

In order to give the user some initial feedback that Stratos is loading, a loading indicator is included in the index.html file. This gets shown as early as possible, as soon as this main html file has loaded. Once the main code has been fetched, the view refreshes to show the application.

A default loading indicator is provided that can be changed. To do so, create the following two files:

  • custom-src/frontend/loading.css - CSS styles to be included in a style block in the head of the index page
  • custom-src/frontend/loading.html - HTML markup to be included the the index page to render the loading indicator

The files for the default indicator can be found in the src/frontend/packages/core/misc/custom folder.

An example of a different loading indicator is included with the ACME sample in examples/custom-src/frontend.

The customization task will insert the appropriate CSS and HTML files into the main index.html file when it runs.

Take a look at the template for the index.html file in src/frontend/packages/core/misc/custom/index.html. The CSS file is inserted where the marker /** @@LOADING_CSS@@ **/ is and the HTML file where <!-- @@LOADING_HTML@@ --> is.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/guides/i18n/i18n/index.html b/website/site-dist/docs/guides/i18n/i18n/index.html new file mode 100644 index 0000000000..a3cffb74e1 --- /dev/null +++ b/website/site-dist/docs/guides/i18n/i18n/index.html @@ -0,0 +1,33 @@ + + + + + + +i18n | STRATOS + + + + + + + + + + + + +
+

i18n

Internationalization (i18n)

WIP

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/guides/metrics/bosh-metrics/index.html b/website/site-dist/docs/guides/metrics/bosh-metrics/index.html new file mode 100644 index 0000000000..c3becbf9fa --- /dev/null +++ b/website/site-dist/docs/guides/metrics/bosh-metrics/index.html @@ -0,0 +1,33 @@ + + + + + + +bosh-metrics | STRATOS + + + + + + + + + + + + +
+

bosh-metrics

Connecting Prometheus-boshrelease to Stratos

Stratos can show some metrics stored in Prometheus.

A Prometheus server is required with a firehose exporter configured to take metrics from the Cloud Foundry Firehose and store them in the Prometheus server.

One option for deploying and configuring such a Prometheus server is with prometheus-boshrelease.

Configuring Prometheus-boshrelease for use with Stratos

In order for Stratos to work with your Prometheus BOSH release, when deploying prometheus-boshrelease you need to set the metrics_environment value.

The metrics_environment value must be set to the value of the doppler_logging_endpoint for your Cloud Foundry, with the prefixing wss:// protocol removed.

For example, for PCF Dev, you would set the metrics_environment value when deploying with bosh, by adding the following to your bosh deploy command:

-v metrics_environment=doppler.local.pcfdev.io:443

Once deployed, you should wait until the firehose target is available and its status is UP.

Connecting Prometheus to Stratos

To view metrics within Stratos, you must connect the Prometheus server to Stratos, to do so:

  1. Go to the endpoints view
  2. Click the '+' icon to register a new endpoint
  3. Select the endpoint type Metrics
  4. Enter a memorable name for your metrics endpoint for the Name
  5. Enter the URL of the Prometheus server for the Endpoint Address
  6. Click 'Finish`
  7. Click on the three-dot menu icon on the right-hand-side of the endpoint you just added above in the endpoints list and click the menu icon
  8. Click 'Connect' in the pop-up menu
  9. Change the Auth Type to No Authentication
  10. Check the Share this endpoint connection - this allows all users to view metrics using this connection. Note that only Administrators will be able to view Cell metrics and that users can only view Application metrics for applications that they have permissions to view.
  11. Click Connect

The view should refresh to show the Metrics endpoint. You can click on the endpoint name in the table to show some basic metadata about the metrics endpoint. If everything is configured correctly, it should show you that the metrics endpoint is providing metrics for your Cloud Foundry deployment.

Metrics should now be available on the view for an Application and also on the Cells tab of the Cloud Foundry view.

PCF Dev Example

The instructions below illiustrate how to deploy and configure prometheus-boshrelease using bosh-lite and a local PCF Dev deployment.

Follow instructions here to bring up a local bosh-lite deployment.

Run these two steps to update the deployment and load the stemcell:

bosh -e vbox update-cloud-config bosh-deployment/warden/cloud-config.yml
bosh -e vbox upload-stemcell https://bosh.io/d/stemcells/bosh-warden-boshlite-ubuntu-trusty-go_agent?v=3468.17 \
--sha1 1dad6d85d6e132810439daba7ca05694cec208ab

Clone the prometheus-boshrelease GitHub repository and change directory into it:

git clone https://github.com/bosh-prometheus/prometheus-boshrelease.git
cd prometheus-boshrelease

You need to create two UAA Clients (ensure you have the uaac CLI installed):

uaac target https://login.plocal.pcfdev.io --skip-ssl-validation
uaac token client get admin -s admin-client-secret
uaac client add cf_exporter \
--name cf_exporter \
--secret prometheus-client-secret \
--authorized_grant_types client_credentials,refresh_token \
--authorities cloud_controller.admin_read_only \
--scope openid,cloud_controller.admin_read_only
uaac client add firehose_exporter \
--name firehose_exporter \
--secret prometheus-client-secret \
--authorized_grant_types client_credentials,refresh_token \
--authorities doppler.firehose \
--scope openid,doppler.firehose

Store the Bosh CA Certificate in a file:

echo $BOSH_CA_CERT > bosh_ca_cert

Get the BOSH URL by examining your config file:

cat ~/.bosh/config

Find the vbox environment and make a note of the url field - set an environment variable BOSH_IP to this value.

You can now deploy Prometheus Bosh Release with:

bosh -d prometheus deploy manifests/prometheus.yml \
--vars-store tmp/deployment-vars.yml \
-o manifests/operators/monitor-bosh.yml \
-v metrics_environment=doppler.local.pcfdev.io:443 \
-o manifests/operators/monitor-cf.yml \
-v system_domain=local.pcfdev.io \
-v metron_deployment_name=local.pcfdev.io \
-v uaa_clients_cf_exporter_secret=prometheus-client-secret \
-v uaa_clients_firehose_exporter_secret=prometheus-client-secret \
-v traffic_controller_external_port=443 \
-v skip_ssl_verify=true \
-v bosh_password=${BOSH_CLIENT_SECRET} \
-v bosh_username=${BOSH_CLIENT} \
-v bosh_url=https://${BOSH_IP}:25555 \
--var-file bosh_ca_cert=bosh_ca_cert

Wait for deployment to complete.

List the instances in the deployment with:

bosh instances -d prometheus

Find the IP Address for the prometheus2 instance. The Prometheus endpoint will be: http://IP:9090.

Open a web browser and load the Prometheus URL. open the Status menu and select targets. Refresh the page until the firehose target is up.

Note: It can take a few minutes before all of the targets appear in Prometheus and their state becomes UP. You should see targets named bosh, cf and firehose as well as many others if everything is working correctly.

You should now be able to follow the Connecting Prometheus to Stratos instructions for registering and connecting Prometheus to Stratos.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/index.html b/website/site-dist/docs/index.html new file mode 100644 index 0000000000..624919c1ec --- /dev/null +++ b/website/site-dist/docs/index.html @@ -0,0 +1,33 @@ + + + + + + +STRATOS | STRATOS + + + + + + + + + + + + +
+

STRATOS

Stratos is an Open Source Web-based UI for Cloud Foundry and Kubernetes.

Note: The Kubernetes additions to Stratos are currently maintained by SUSE and we are in the process of upstreaming these to the cloudfoundry GitHub repository and making them a standard part of the Stratos build and install.

For Cloud Foundry, it allows users and administrators to both manage applications running in the Cloud Foundry cluster and perform cluster management tasks.

For Kubernetes, it provides Developers with views of their Kubernetes resources, the ability to view and deploy Helm Charts and view Workloads.

Stratos Application view

Quick Start

To get started quickly, we recommend following the steps to deploy the Stratos Console as a Cloud Foundry Application - see here.

If you have docker installed, you can quickly deploy Stratos using the all-in-one container:

$ docker run -p 4443:443 splatform/stratos:latest

Once that has finished, you can then access Stratos by visiting https://localhost:4443.

Deploying Stratos

Stratos can be deployed in the following environments:

  1. Cloud Foundry, as an application. See guide
  2. Kubernetes, using a Helm chart. See guide
  3. Docker, single container deploying all components. See guide

Troubleshooting

Please see our Troubleshooting page.

Further Reading

Get an Overview of Stratos, its components and the different ways in which it can be deployed.

Browse through features and issues in the project's issues page.

What kind of code is in Stratos? We've integrated Code Climate for some code quality and maintainability metrics. Take a stroll around the project page

Contributing

We very much welcome developers who would like to get involved and contribute to the development of the Stratos project. Please refer to the Contributing guide for more information.

For information to help getting started with development, please read the Developer's Guide.

Support and feedback

We have a channel (#stratos) on the Cloud Foundy Slack where you can ask questions, get support or give us feedback. We'd love to hear from you if you are using Stratos.

You can join the Cloud Foundry Slack here - https://slack.cloudfoundry.org/ - and then join the #stratos channel.

License

The work done has been licensed under Apache License 2.0. The license file can be found here.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/overview/index.html b/website/site-dist/docs/overview/index.html new file mode 100644 index 0000000000..f5fb621e56 --- /dev/null +++ b/website/site-dist/docs/overview/index.html @@ -0,0 +1,33 @@ + + + + + + +Stratos Overview | STRATOS + + + + + + + + + + + + +
+

Stratos Overview

The Stratos Console provides a web-based UI to allow developers and administrators to manage their applications and cloud foundry deployment(s).

It is designed to manage one or more Cloud Foundry deployments. It does so by managing "endpoints", where each endpoint is a reference to a Cloud Foundry deployment. The notion of an endpoint is not specific to Cloud Foundry, allowing Stratos to connect to other service types in the future.

Stratos stores endpoint metadata in a relational database. Administrators of Stratos are able to register (add) new endpoints to the Console. All users are able to then connect to these endpoints using their credentials, ensuring that they get the appropriate level of access when interacting with Cloud Foundry.

The high-level architecture of Stratos is shown in the diagram below:

Stratos High-Level Architecture

The main components:

  • Web UI - Single-page AngularJS web application providing the front-end that runs in the user's browser.
  • API Server - Provides the back-end APIs that support the front-end UI. This API takes care of authentication, endpoint management and proxying API requests from the front-end to the desired back-end API.
  • Endpoint Datastore - Relational database that stores the registered endpoints and the encrypted user access tokens.

Authentication

Stratos UI authenticates users using a Cloud Foundry UAA service. It must be configured with the details necessary to communicate with a UAA. When the user logs in to the Console, their login will be validated with the UAA. The Console uses a scope to identify Console administrators from regular users.

Administrators use the 'Endpoints Dashboard' within the Console to add new endpoints to the Console. All users are then able to connect to these endpoints by providing their credentials. The Console will use these credentials to communicate with the UAA for the given endpoint (typically Cloud Foundry) and obtain a refresh and access token. These tokens are encrypted and stored in the Endpoint Datastore.

When a user interacts with the Console and API requests need to be made to a given Cloud Foundry endpoint, these are sent to the API Server along with a custom http header which indicated which endpoint(s) the requests should be send to. The API Server will forward the request to the appropriate endpoints, first looking up the access and refresh tokens required to communicate with the endpoint(s). If any access token has expired, it will use the refresh token to obtain a new access token.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/planning/angular/index.html b/website/site-dist/docs/planning/angular/index.html new file mode 100644 index 0000000000..26aa7e1d5d --- /dev/null +++ b/website/site-dist/docs/planning/angular/index.html @@ -0,0 +1,33 @@ + + + + + + +angular | STRATOS + + + + + + + + + + + + +
+

angular

Technology Refresh

The focus for the first part of 2018 is to complete the move from AngularJS to Angular. This is a significant amount of work.

Migrate Angular from AngularJS

Move to a newer framework that is being actively developed and will carry us forward for longer. This will make future migrations much easier (Angular 2 => 4 => 5 => 6)

Note:

  • Back-end stays the same (folder structure will most likely be moved around)
  • Deployment and other scripts, artefacts remain the same (tweaks as necessary to build the V2 code)

Stack:

  • Angular 5
  • Typescript
  • RxJS
  • Angular Material

Migrate to Material Design

Adopt material design while keeping essence of the current Angular 1 app:

  • Use Material Design as the visual language for the UX
    • Rich language
    • Used by a growing number of projects, not just those from Google
  • Adopt Material Design approach, patterns and components
  • Leverage angular-material library for UI components
  • Only create custom components when needed
  • Adopt angular-material approach to theming
  • Improve layout and use more visual cues to help locate date and issues

Migration Milestones

This material is out of date. We will update once schedule planning is complete.

Milestone 1: CF Applications -> Endpoint mgmt and Application views (Complete in Sprint 22)

  • App Wall
  • App View
    • Edit
    • Routes
    • Instances
    • SSH
  • Endpoints

Milestone 1b (Complete in Sprint 22)

  • Deployment of an Application as per V1.

Milestone 2 (Complete in Sprint 24)

  • Cloud Foundry View (excluding "assign users")

Milestone 3 (Complete in Sprint 26)

  • Services view
    • Services as a top-level concept
    • Improve support for services: Service Keys etc

Milestone 4: Misc (Complete in Sprint 28)

  • Add dashboard
  • About page
  • User profile viewing and edit

Milestone 5 (Complete in Sprint 30)

  • Equivalent functionality of "Assign Users"

To be scheduled into Milestones:

  • e2e tests
  • unit tests
  • error handling
  • Support for plugins/extensions
  • Support for vendor modifications
  • Internationalisation (i18n)
  • Theming/Branding
  • Deployment support
    • cf push
    • helm
    • bosh
+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/planning/cf-user-management/index.html b/website/site-dist/docs/planning/cf-user-management/index.html new file mode 100644 index 0000000000..5b689976f4 --- /dev/null +++ b/website/site-dist/docs/planning/cf-user-management/index.html @@ -0,0 +1,35 @@ + + + + + + +cf-user-management | STRATOS + + + + + + + + + + + + +
+

cf-user-management

Cloud Foundry User Management

Requirements

  • View the organisation and space roles for all users
  • Edit the organisation and space roles for a specific user
  • Assign multiple organisation and/or space roles for multiple users

V1

  • Users tab + table at CF, organisation and space level
    • CF level shows user organisation roles for all organisations as pills
    • Org level shows user space roles for all spaces as pills
    • Space level shows user space roles for space as pills
  • Table provided links to update roles
    • 'Manage' a single user - pop up showing orgs/spaces (depending on level) roles. Allowed edit of all shown roles
    • 'Change' multiple users - similar to manage, however no existing roles were shown. New selection replaced existing roles
    • 'Remove all' roles of selected users. These are specific to the level (cf - remove all orgs/spaces, org - remove all org/spaces, space - remove all space)
  • All cf/org/space pages allow user to 'Assign' roles in a pop up
    • pop up contains stepper, one stage to select user/s and another role/s
    • can only assign roles to a single org and it's spaces
    • no existing roles are shown

V1 Issues

  • Handling large amount of orgs or spaces
    • Pill format to represent user roles lead to potentially large blobs of pills which were hard to extract information from but did show +the data in as small as possible area
    • The Manage/Change popup didn't scale well at the CF level for lots of orgs or org level for lots of spaces
  • Only showing org or space roles in the table can lead to confusion, for example user edits org roles at space level and no changes to table.
  • Multiple ways to reach the same window (buttons above tables, row actions)
  • Can only mass assign roles one org at a time
  • No concept of inviting users
    • Need to understand how this would work by supplying an email. API provides a way to create users with their UAA guid

V2

First pass implementation - Changes to V1

  • 'Change' multiple user modal
    • To be removed. The ability to 'reset' multiple users needs more work.
  • 'Manage' single user modal
    • Only allow edit of a single org and it's spaces in the 'Manage' pop up, as per the assign. This restricts functionality but presents the +information in a clearer way and scales much better for multiple orgs.
    • Tidy the position of 'remove from org'
    • Stretch - Remove the 'org user' and handle automatically in the background?
  • 'Assign'
    • Step 2 - Ensure consistent UX with 'Manage' or vice versa
  • Users Tab/Table
    • Show org and space columns for their roles. Relevant to level (cf - both, org - both, space - space only)
    • Provide a way to collapse list of roles automatically when there's a large amount.
    • Stretch - Provide a way to filter per role. This will allow user to quickly see who's, for instance, a manager.

Second pass

  • Invite/Create user
  • Remove user
  • Reset users roles

Design input required pre release

  • Validate first pass approach
  • Review use case/possible solutions to update/reset multiple users roles
  • Review use of pills in table
  • Review second roles column in table
  • Review Manage/Assign layout

Similar Implementations

High level description of other CF UIs

  • Management at org and space level
    • Roughly table like views
    • Each user listed in rows
    • Org/Space roles as columns
  • Editing a users roles by..
    • a check box in the roles column (each change an individual api request at time of click)
    • a pop up allowing edits to all org OR space roles for a specific row/user
    • All edits are very specific to user
  • Provide a way to invite new users by email address.
    • Can specify what roles they have at invite time

Note .. There's no easy way to check user/s management at Cloud Foundry admin level, which is where some of the fun starts.

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/planning/metrics/index.html b/website/site-dist/docs/planning/metrics/index.html new file mode 100644 index 0000000000..f72068dc58 --- /dev/null +++ b/website/site-dist/docs/planning/metrics/index.html @@ -0,0 +1,36 @@ + + + + + + +metrics | STRATOS + + + + + + + + + + + + +
+

metrics

Metrics

We would like to add Metrics into Stratos.

The goal is to be able to view metrics over time for Applications as well as for aspects of a Cloud Foundry deployment.

The current thinking is that we would deploy Prometheus to collect and store metrics and would use the Cloud Foundry Exporter to channel the data +from the Cloud Foundry firehose into Prometheus.

Since Prometheus does not provide any authentication, we would look to deploy nginx in front of the Prometheus server so that access its API +can be gated. We would most likely use basic authentication and ensure HTTPS access only to the API endpoint.

This basic setup would allow an administrator to deploy Prometheus and configure it to collect metrics from a Cloud Foundry deployment and for APi of Prometheus to be accessed securely.

An intial PoC to get Prometheus deployed with a firehose exported using Helm is here - https://github.com/SUSE/stratos-metrics.

In Stratos, we would add a new endpoint type "Cloud Foundry Metrics" that a user can register with the endpoint of the Prometheus API and then connect to with their credentials as configured above. This would allow the Stratos backend to be able to talk to Prometheus securely and retrieve metrics.

We may need to add some metadata that can be retrieved from Prometheus or the nginx gating it, so that Stratos can determine which Cloud Foundry it is providing metrics for. It may provide metrics for multiple Cloud Foundry deployments.

We will extend the Stratos backend API to allow Prometheus queries to be made via its API. To ensure that a user only sees metrics for entities that they are permitted to see, we would create endpoints along the lines of:

  • Metrics for an Application = /metrics/app/{app-id}/query?query=PROMETHEUS_QUERY
  • Metrics for Cloud Foundry = /metrics/cf/query?query=PROMETHEUS_QUERY

In the case of Application metrics, the Stratos back-end will first make an API call to Cloud Foundry to retrieve the specified application, in order to determine that the user +is permitted to access the application in question.

In the case of Cloud Foundry metrics, the Stratos back-end will check the user's scopes to ensure that they are an administrator of the Cloud Foundry in question.

References:

  1. https://prometheus.io/docs/prometheus/latest/querying/basics/
  2. https://prometheus.io/docs/prometheus/latest/querying/api/
  3. https://github.com/bosh-prometheus/firehose_exporter
+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/planning/services/index.html b/website/site-dist/docs/planning/services/index.html new file mode 100644 index 0000000000..21dbc89aee --- /dev/null +++ b/website/site-dist/docs/planning/services/index.html @@ -0,0 +1,34 @@ + + + + + + +services | STRATOS + + + + + + + + + + + + +
+

services

Services

GitHub issue: #1391

The goal with this feature is to provide first-class Services support in Stratos. Up until now, Services support was limited to:

  • Viewing the service instances in a space and being able to delete these
  • Creating a service instance an bind it to an application

Going forward, we want to be able to expose all fo the concepts around Services that are exposed via the API, namely:

  • Services
  • Service Instances
  • Service Keys
  • Service Plans (and plan visibility)
  • User-provided Service Instances
  • Service brokers

We also want to track the Open Service Request Broker work and ensure that thi sis reflected in Stratos.

First Class Support

By "First class Support" we mean that Services will become a top-level item in the side-navigation menu, much like Applications is today.

Since Stratos allows multiple Cloud Foundry deployments to be manged, this means that the Services views we add will need to aggregate service information in the same was that the Applications view does, including being able ot filter by a specific Cloud Foundry deployment, org and space.

Unlike the Application view, where we only have one entity to display (i.e. Applications), for Services, there are a number of entities that we may wish to choose from:

  • Services (i.e. the marketplace or catalog)
  • Service Instances (the actual instances that have been created from the catalog)
  • Service Plans
  • Service Keys
  • Service Plan Visibilities
  • User-provided Service Instances

UX

(Thanks to Guillaume Berche and team for their input)

To distinguish between the Service Catalog (Marketplace) and Service Instances, we will break-out two top-level navigation items that will appear in the left-hand nav bar:

  1. Marketplace - showing the Service Catalog

  2. Services - showing Service Instances

Marketplace

This will show the Service Catalog. When multiple Cloud Foundry deployments are connected, we will show a filter control to filter the view by CF/Org/Space as we do with applications.

Provides both a card and list view.

Clicking on a card or name in the list will take the user to a more detailed Service Definition View.

Service Definition View

This shows:

  • Metadata as per the card/list
  • Service long description (although)
  • Service plans (and not the aggregated number of service plans) as depending on the current logged in user, the visible service plans differ) along with their description and meta-data (including price)
  • Button to enable a service instance to be created for this service

(ref: https://apidocs.cloudfoundry.org/1.27.0/services/retrieve_a_particular_service.html)

Services

This will show Service Instances. When multiple Cloud Foundry deployments are connected, we will show a filter control to filter the view by CF/Org/Space as we do with applications.

Provides both a card and list view.

This shows:

  • General metadata
  • Which space the service belongs to
  • Which spaces the service has been shared with

Clicking of a Service Instance will drill down into a Service Instance Detail view.

Service Instance Detail View

Shows:

  • General Metadata
  • Service plan
  • Service parameters (in the future thanks to OSB GET endpoints see servicebroker/issues/159
  • Service keys for this instance

Enable updates:

  • in service plans
  • in parameters

Enable delete

Service Instance Creation

Stratos will support the following two flows for creating service instances:

  1. Service Plan driven Flow: In this flow the user starts off by selecting the service plan for the instance they want to create.
  2. Org/Space driven Flow: In this flow, the user starts off by selecting the organisation and space in which they desire to create an instance.

The following outlines these two flows in more detail.

Service Plan driven Flow

From the Marketplace, the user should be able to select a service plan and provision a service instance using that plan.

When a specific service plan is selected, the following considerations need to be made:

  1. If a service plan is public, it is available to all organisations and spaces. Therefore, the user should be able to select any organisation or space.
  2. If a service plan is not public, then service visibilities should be checked and the user should only be allowed to selected the organisation for which a service visibility has been defined by the admin.
  3. If a service plan is not public and no service visibility exists for it, the user should not be able to select the plan.
  4. If the service plan is provided by a service broker that is space-scoped, then the values for the organisation and space should be pre-populated and locked.

The wizard should support parameters with generated form created from JSON schema, see stratos/issues/1434

Org/Space driven Flow

From the top level Services view, the user should be able to create a new instance. In this flow however, the user starts with selecting the organisation and space they want to create the service instance in. +Based on that selection, the appropriate service definitions and service plans should be displayed, following the same considerations as specified for the previous flow.

Services Binding Detail view

This will show a Service Binding.

Shows:

  • Service Instance
  • Bound Application (optional)
  • Service binding parameters (in the future thanks to OSB GET endpoints see servicebroker/issues/159
  • Credentials (using JSON or in the future generated form thanks to binding credentials output JSON schemas servicebroker/issues/116

Enables updates:

  • in parameters (in future OSB spec version)

Enables delete (i.e. unbind service from app)

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/roadmap/index.html b/website/site-dist/docs/roadmap/index.html new file mode 100644 index 0000000000..fadd59d0ba --- /dev/null +++ b/website/site-dist/docs/roadmap/index.html @@ -0,0 +1,33 @@ + + + + + + +roadmap | STRATOS + + + + + + + + + + + + +
+

roadmap

Stratos Roadmap - Out of date

Last Updated: 2 July 2018

Version 2 Timeline

The current focus is on releasing V2 of Stratos. The current timeline is:

DateMilestone
15 JuneBeta 1
20 JuneBeta 2
25 JuneRC 1
29 JuneRC 2
20 July2.0.0

Post 2.0 is released we will be working towards a regular recycle cycle each Sprint - we may start with Monthly releases and finally to releases each 2 weeks.

Agile

We work on a 2-week Sprint cycle. Sprints start on Wednesdays. For reference, Sprint 27 started 4 April 2018.

We are using GitHub issues to track all work items. See: https://github.com/cloudfoundry/stratos/issues

High-Level Features

The high-level features that we schedule into the roadmap are identified by the feature-request label. You can see the current set of features here.

Near-term roadmap

#DescriptionIssueNotes
1Technology Refresh (AngularJS => Angular)#1972Notes
21st class support for service plan & service instance#1391Notes
3Add support for Application and CF Metrics#1985Notes
4Support UAA login UX directly (SSO)#1384
5Support per-endpoint Client ID and Client Secret#2220
6Bring Orgs and Spaces view to top-level#2619
7Deploy application: Enable deploying from private Git repositories#1442
+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/status_updates/index.html b/website/site-dist/docs/status_updates/index.html new file mode 100644 index 0000000000..4352da38d3 --- /dev/null +++ b/website/site-dist/docs/status_updates/index.html @@ -0,0 +1,35 @@ + + + + + + +status_updates | STRATOS + + + + + + + + + + + + +
+

status_updates

Status Updates

Weekly status updates are published here.

12 April 2019

This week the Stratos team has been...

  • Presenting Stratos v2.4 features to the community in the latest project update
  • Working towards phase two of the extension project.
  • Finishing off the remove roles from cf user feature.
  • Finishing off adding an optional 'connect' step to the register endpoint stepper.
  • Reviewing and shepherding PRs into master, minor bug fixes.

5 April 2019

This week the Stratos team have mostly been ...

  • Improving e2e reliability and merging existing PRs.
  • Improving the create/deploy app flow. Users will now only be presented with a single button to start the flow. Their first step is to decide where the source for the app will come from (github, gitlab, locally, etc) or to create without source.
  • Removing the endpoints page when there's no persistent storage. This is now on par with the home/favourites page.
  • Adding an option that will allow the user to stay signed in to the console (if option is checked and the page remains visible).
  • Starting working towards the ability to remove all roles from a cf user with a single click (after confirmation).
  • Starting working towards an optional 'connect' step when registering an endpoint.
  • Fixed a few minor trivial bugs

22 March 2019

This week:

  • Work continues to complete the addition of support for Cloud Foundry User Provided Services. This is almost done. A few small issues and corner-cases cropped up which we have been working on.
  • Added support for slide-in help content and wired this into the endpoint connection dialog
  • We continued to refine the visual presentation of endpoints within Stratos

15 March 2019

This week:

  • Enhancing the endpoint registration view to use a tile selector
  • Updating our docs on our use cases and requirements for the Cloud Foundry V3 API

8 March 2019

This week:

  • Added a card view to the endpoints view
  • Continued to refine the support for User Provided Service Instances
  • Working on support to allow list views to show different entity types in the same list
  • Ensured features requiring persistence database are not enabled when using SQLite

1 March 2019

This week:

  • Updated the front-end code to use Angular 7 (in review)
  • Continued to add support for User Provided Service Instances
  • Reviewed, tweaked and merged our first phase of work on improving extensions support

22 February 2019

This week:

  • The user invite feature has been reviewed and merged
  • Front-end code restructuring to support next phase of extensions work
  • Pre-work for update to Angular 7
  • Add support for User Provided Services
  • Updates to our documentation on our needs for the Cloud Foundry V3 API

Important:

Hello All - Two CVEs in Stratos were recently discovered - both are fixed in 2.3.0 - so we encourage you to update to that latest version to address these issues. Both relate to the session cookie:

https://www.cloudfoundry.org/blog/cve-2019-3783/ +https://www.cloudfoundry.org/blog/cve-2019-3784/

Deployment Survey

We want to understand more about how everyone is deploying Stratos - so we can better support the most used deployment scenarios and (possibly) remove some of the deployment mechanisms that aren’t being used - we’ve got a quick survey we’d love it if you could fill out: https://www.surveymonkey.co.uk/r/MLXDMKG

15 February 2019

This week:

  • 2.3.0 was Released!
  • The user Favourites feature has been reviewed and merged
  • We continue to fix and merge many of the outstanding PRs around User Favourites and Scalability
  • We spent half a day reviewing our next steps to re-structure the front-end code as part of our work towards the next phase of extensibility.
  • We continue to improve the suite of automated deployment tests that run continuosuly

8 February 2019

Release 2.3.0 is all ready to go and we will publish this on Monday.

Otherwise, we've been working on:

1 February 2019

We are looking to release 2.3.0 next week having completed testing.

Work has otherwise continued on four tracks:

  • Closing out existing PRs
  • Finishing a first version of the User Favourites feature
  • Finishing a first version of the User Invitation feature
  • Improving test automation

25 January 2019

This week:

  • Published a release candidate for Stratos 2.3.0 which we continue to test
  • Worked to update a few outstanding PRs - we are aiming to close out some of the remaining PRs this sprint, ahead of a re-org of our front-end code to better support extensions to Stratos in the future
  • Continued to refine the User Favourites feature
  • Worked to add the ability to invite a user into a Cloud Foundry organisation
  • Continued to improve the reliability of automated deployment tests in Jenkins

18 January 2019

We created a test release of 2.3.0 and identified a number of issues to be resolved for release.

The remainder of this week was spent fixing the issues identified.

A 2.3.0 Release Candidate will be published later today or on Monday of next week.

We hope to finish testing and publish the 2.3.0 release next week.

The 2.3.0 Change Log has been updated and is available here

11 January 2019

Happy New Year!

The focus of the week was in preparing 2.3.0 release:

  • We reviewed, updated and merged over 20 outstanding PRs that were targeted at 2.3.0 release
  • We’ve made some improvements to our Helm chart to the external service configuration
  • We’ve tweaked our release process and updated and improved our Concourse release pipelines
  • Performed initial testing of 2.3.0 build

We expect to create a Release Candidate next for 2.3.0 so QA can kick the tyres as well.

We’re also looking at the roadmap for this year and planning our releases throughout 2019.

21st December 2018

Rounding off our year, here's some highlights from the last few weeks.

  • User Favourites - Great progress has been made and we're almost ready to merge to master.
  • Page Tabs & Side Nav Update - The horizontal tabs shown in sections such as Application, Cloud Foundry, Organisation, etc have found a smart new home in a side nav. For screenshots see PR #3289

PRs:

  • Add a routes list to the CF tabs, Routes Refactor & Route Bug Fixes (#3292)
  • Add deployment info for apps deployed via docker & fix info for local/archive apps (#3291)
  • Improve focus & tabbing (#3288)
  • Application Env Var fix & improvements (#3286)
  • Fix exception when navigating away from the first deploy app step (#3277)
  • Add service plan tab to service pages (#3275)
  • List Multifilter Improvements (don't show cloud foundry selector if there's only one connected) (#3270)
  • Update side nav logo with light version of new logo (#2921)
  • Hide app vars tab if user is not a space developer (#3247)
  • Show app chip list for space routes list bound apps (#3041)

Community PRs:

  • Fixes Async Service Provisioning Bug (#3090) (merged)
  • [autoscaler] add autoscaler tab in app page (#3266)

7th December 2018

The team are continuing to tackle some of the smaller issues form the backlog as well as the following two features:

  • User Favorites - Allowing users to favorite Apps, Orgs, Spaces etc and to provide quick access to these items.
  • Inviting Users - Support for inviting users to a Cloud Foundry system via email and to grant appropriate rights to an Org/Space

PRs:

  • Reduce size of Docker All-in-one image #3261
  • Tidy up CLI login info #3269
  • Add service provider name to marketplace service card #3268
  • Add link to dashboard in service instance table #3267
  • Add Org and Space status bar to Org/Space Cards #3265
  • Helm port configuration improvements and unit tests #3264
  • Add confirmation dialog to Restage app #3263
  • Remove global manage apps link #3259
  • Add user has roles filter to users tables #3258

30th November 2018

A quieter week for the Stratos team - with some out on vacation as we head towards the festive season.

PRs this week:

  • Make the table multi actions more obvious #3251
  • Hide app vars tab if user is not a space developer #3247
  • Improve resilience of e2e tests #3246
  • App Wall filter and sort controls size tweaks #3243
  • Deploy App: Add notification toast #3242

23rd November 2018

We've been continuing to test Stratos 2.2.0 and improving test automation and E2E test reliability.

We've started to work through some of the GitHub issues - the focus for the next couple of sprints is to fix and close out some of the smaller issues and bugs.

We're also working to improve the scalability of Stratos with large numbers of Apps/Orgs/Spaces/Users.

PRs this week:

  • App Deploy: Add Public GitLab Repository support #3239
  • Fix CLI info formatting #3237
  • Show better error message on login screen when account locked #3235
  • Add Route: Use correct label for submit button #3231
  • Fix for cancel broken on add route #3228
  • Backend: Update to latest version of Echo Web Server #3216
  • Show refresh button for latest modified application lists #3213
  • Scalability: Handle large number of apps in cf dashboards #3212
  • Support prometheus-boshrelease as a metrics endpoint #3202
  • Fix alignment of arrow when no endpoints registered #3234
  • Run customize when prebuild and log node and npm versions #3232
  • Add stricter check for jetstream error object #3223
  • Improve paginated/pagination action naming #3218
  • Fix display of generic error bar #3214
  • Only show + icon when we have at least one connected CF #3211

16th November 2018

This week the team has been working on:

  • Testing Stratos 2.2.0
  • Enabling Extensions to be published separately
  • Test automation
  • E2E Test reliability
  • Space service tidy up #3197

9th November 2018

This week the team has been:

  • Testing Stratos 2.2.0
  • Working towards enabling Extensions to be published separately
  • Updating developer documents: #3184
  • Adding initial document for back-end plugins: #3189
  • Fixed bug with deploying with folder upload: #3191

2nd November 2018

This week we have mostly been:

26th October 2018

The team were away attending a workshop this week.

The only item of note is that we have now forked the go-flags package that was causing broken dependency issues for us and updated Stratos to use this package. This should allow us to avoid future issues with this package.

19th October 2018

We are preparing for this month's 2.2.0 release which will be out towards the end of the month.

Highlights for this week:

  • Extensions: Fix for side nav. Add initial docs #3140
  • User menu improvements #3136
  • Metrics: Show table of cell health state changes instead of chart #3135
  • Metrics: Update app instance cell data when scaling up #3133
  • Metrics: Ensure CF Cells info is shown for non cf admins #3121
  • Add 'type text to continue' to confirmation modal #3131
  • Delete App Stepper: Disable delete of routes and services that are bound to other app/s #3129
  • Endpoints Table: Only show 'Admin' check icon for cf endpoints #3132

12th October 2018

The team have been preparing for and attending the CF Summit in Basel.

5th October 2018

The team have been preparing for the CF Summit in Basel next week.

Highlights for this week (continuing from last week):

  • E2E Tests and Automation - Focusing on making the E2E tests more resilient to timing issues.

  • Metrics - Added Diego Cell to the App Instances table when metrics are available and added a Cell view which shows metrics for a given Diego cell.

Fixes:

  • Ensure we handle orgs with no users #3098 - fixes a bug creating a space in a new org.

  • Endpoint Registration: Only show SSO option for CF Endpoint type #\3105

28th September 2018

This week saw the release of 2.1.1 and an update 2.1.2. It was necessary to tag a 2.1.2 release to resolve a broken backend dependency that would affect users deploying via 'cf push'. You should use 2.1.2 and not 2.1.1.

2.1.2 Highlights

  • Fix go-flags dependency pinned version broken #3071

  • App wall filtering can stop working with some filter combinations #3043

  • Can not connect a metrics endpoint #3035

  • Backend build issue due to the pinned commit for a dependency being removed #3060

  • Metrics: Wrong job can be matched up when there are multiple jobs #3057

Highlights for this week (continuing from last week):

  • Extensions - Work continues on adding extension points in the UI. Extensions is targeted for 2.2.0 in October.

  • E2E Tests and Automation - Focusing on making the E2E tests more resilient to timing issues.

  • Metrics - Work to tidy up the existing Cloud Foundry Application metrics is complete.

21st September 2018

This week saw the release of 2.1.0 - the highlights are:

  • Stratos frontend can be pre-built before pushing to Cloud Foundry to enable AOT and reduce push time
  • SSO support refinements with the ability to now connect a Cloud Foundry endpoint using SSO in addition to SSO login to Straos itself
  • Ability to specify manifest overrides when deploying an application
  • Ability to optionally specify Client ID anc Client Secret when registering an endpoint
  • Add ability to restage an application
  • Endpoints list now shows logged in user's username and whether they're an admin
  • Switched to new Stratos logo for login and about pages
  • Backend improvements to make it easier for developers to develop with
  • Security fixes

Full release information is available here.

Highlights for this week (continuing from last week):

  • Extensions - Work continues on adding extension points in the UI. Extensions is targeted for 2.2.0 in October.

  • E2E Tests and Automation - Focusing on making the E2E tests more resilient to timing issues. We have also spent time getting the E2E tests to run against BrowserStack to allow us to automate testing of Stratos across multiple browser types/platforms.

  • Metrics - Work to tidy up the existing Cloud Foundry Application metrics is complete.

  • JSON Schema support for Service Instance binding - We have been working to update PR #2997 to get this feature into Stratos.

Fixes/Misc:

  • Fix app wall filtering issue #3043
  • Fix for Connect button not being enabled when SSO is the default #3004
  • Version number always reports 'dev' #3001
  • Diagnostics does not show GitHub details when cloned via HTTPS #3007
  • Fix for NULL Client Secret bug #3015
  • Fix bug where token IDs are not set properly when upgrading from a previous version #3017

14th September 2018

We've been preparing the 2.1.0 release this week. This will be published next week. Going forward we will be publishing a new release every month. The release notes for 2.1.0 have been created and are here.

Highlights for this week:

  • Extensions - Work continues on adding extension points in the UI. We have PRs up to support adding new side-nav items, tabs and actions. This already goes beyond what could be done in V1 of Stratos. The extension mechanism is also much cleaner due to the use of decorators. Extensions is targeted for 2.2.0 in October.

  • E2E Tests and Automation - Continuing to build out the E2E test suite and automate the deploy and test of Stratos in different environments (pushed to Cloud Foundry, pushed to Cloud Foundry with MySQL and Postgres, pushed to Cloud Foundry with SSO, Docker compose, Docker All-in-One)

  • Metrics - Work is almost complete on improving the metrics integration and presentation in the UI. Rather than display a timeline under each graph, we are switching to a control to allow you to choose the time period.

Other updates:

  • Allow auto-registration name to be configured #2986
  • SSO: Refinements #2982
    • Fix consistency of SSO casing and hyphenation => 'Single Sign-On'
    • Make SSO default when connecting if enabled for the endpoint
    • Move the SSO Allowed checkbox to the bottom in 'Advanced Options', so that the form does not move when the checkbox is checked and the advisory text appears
  • Add check to make sure DB Schema migrations have completed (fixes an issue with diagnostics and a possible race-condition when deployed via Helm or Docker Compose) #2977

7th September 2018

Update for this week:

  • Single Sign-On - Added the ability to enable SSO Login when using the Setup screen.

  • Metrics - Work continues to improve the metrics integration and presentation in the UI

  • Extensions - Work has started on adding extension points in the UI. This will be accomplished via decorators, in the same way that Angular uses decorators for Components etc. #2962

  • Deploy App Manifest overrides - Added an extra step in the 'Deploy App' flow to allow you to override manifest settings before deploying #2924

  • Show Service plan cost when selecting a service plan (if not free) #2959

  • E2E Tests - Resolved GitHub rate limits issues when running E2E Tests #2949

  • Travis - The Travis build has been restructured to run jobs in parallel and E2E tests now run against PRs in addition to branches.

31st August 2018

Update for this week:

  • Go-backend re-structure - The additional cleanup work has been merged.

  • Single-Sign-On - Further work on Single-Sign On:

    • Improvements - improve error handling, add navigate straight to login option #2522
    • Link tokens rather than copying them #2916
    • Allow a Cloud Foundry endpoint to be connected with SSO login #2928
  • Allow Client ID and Secret to be set when registering an endpoint #2920

  • Scalability:

    • Change application list in service instance table row from vertical to chip list #2915
    • Convert space apps list from local to remote #2913
  • Metrics - Work has started on tidying up and improving the metrics views

24th August 2018

Update for this week:

  • Go-backend re-structure - This work has now been merged and should make it easier to develop with and contribute to. Some additional clean up was done and is awaiting PR review.

  • Extended end-to-end test suite - Further work to build-out the E2E test suite. See:

    • Services E2E: Service Instance creation with App Binding #2855
    • E2E: Basic Application Routes tests #2862
    • E2E: Basic Application Instances tests #2863
    • E2E: Basic test for Cf/Org/Space users tables #2904
  • Small improvements and fixes for the Diagnostics page #2860

17th August 2018

Update for this week:

  • 2.0.1 - We tagged a 2.0.1 release. This is identical to 2.0.0 and only fixes an issue with a broken dependency - one of the pinned dependencies was no longer working. This issue only affects you if you were pushing to Cloud Foundry from the 2.0.0 tag.

  • Pre-built UI - We added the ability to pre-build the UI before pushing to Cloud Foundry. This allows you to build the UI with AOT (Ahead-of-time) compilation enabled and push to CF. This will also reduce push time. See the doc Pre-building the UI.

  • Go-backend re-structure. Work is almost complete on re-structuring the go backend to make it easier to develop with and contribute to. See issue #2815.

  • Extended end-to-end test suite

10th August 2018

A similar update to last week, focusing on metrics, testing and the community.

  • Testing the new metrics deployment process.
  • Improving the end to end test setup process, this will enable better coverage of service tests.
  • Improving test coverage, both unit and end to end, of the often used list component.
  • Improving test coverage of entity validation, another often used component.
  • Manage application stats requests better in the application wall when there are many many started apps.
  • Investigating, solving and shepherding community issues. Some of the stand out ones..

3 August 2018

This week we've focused on..

  • Making metrics components easier to deploy. This will help us apply polish and publicise CF metrics in the coming weeks.
  • Improving test suites and coverage.
  • Responding to community issues. There's been an increase in use and some great contributions.
  • Fixing older, but still valid, issues that haven't quite been important to address at the time.

In addition we’ve created a short (a few minutes) survey to get a better idea how the community plan to use Stratos. Answers and feedback will directly impact the direction we take Stratos, so the quicker we have responses the quicker we can act on them. Follow this link to start answering https://www.surveymonkey.com/r/2L8XWST

27 July 2018

The main news this week is that we have released a first version of Stratos 2.0.

We've been focused over the past weeks on fixing bugs and improving tests and we're delighted to have reached this milestone.

The release details are available here - https://github.com/cloudfoundry/stratos/releases/tag/2.0.0.

We've also started to catch up on some of the outstanding PRs, especially submitted from the community, for example:

  • Change DB schema and backend to support storing a client/secret for each Endpoint #2622
  • Fix migrate script to work in Postgresql #2601

20 July 2018

This week the focus has been on further testing and refinement of Release Candidate 2.

We will be publishing a Release Candidate 3 on Monday 23 July. We expect this to be the final RC and will most likely promote this to be the final Version 2 release later next week.

We've been focused on more test automation and building out more end-to-end tests, in addition to fixing a few bugs.

We had an issue with the Angular AOT + build optimization which pushed the final RC into next week. This took a while to get to the bottom of.

For a full list of merged PRs this week, see: Merged PRs.

13 July 2018

The SUSE team has been participating in SUSE Hack Week, so there is no change in status this week.

Work resumes next week on getting a first 2.0 release published.

06 July 2018

This week the focus has been on further testing and refinement of Release Candidate 2.

We've been identifying and fixing issues - see: Merged PRs.

29 June 2018

This week the focus has been on creating a Release Candidate of Version 2.

In fact, we published two Release Candidates - at the start and end of the week - full details here: +https://github.com/cloudfoundry/stratos/releases

A large number of bugs and smaller issues have been resolved since last week's Beta 2 release - full details here: https://github.com/cloudfoundry/stratos/compare/2.0.0-beta-002...2.0.0-rc2

Work has been focused on testing the Release Candidates and fixing defects.

22 June 2018

This week the focus has been on creating a second Beta release of Version 2.

A large number of bugs and smaller issues have been resolved - full details here: https://github.com/cloudfoundry/stratos/releases/tag/2.0.0-beta-002.

15 June 2018

We are working towards a release of V2. We are now functionally complete and are working through priority 1 issues and defects.

We've been working through a large number of defects this week -

  • Deploy info card shows both file and folder info #2351
  • App Service Instances: Modal appears off screen #2347
  • Users list is empty after cancel #2339
  • We still show large no connected CF endpoints even when you connect a metrics endpoint #2332
  • Connected endpoint does not show 'unregister' action #2321
  • Service instance page shows no 'no cf connected' warning #2320
  • No page header on Cloud Foundry pages when you go directly there #2319
  • Service Instance entity is not updated after unbinding an app #2317
  • Service broker card intermittently appears immediately below service summary card #2314
  • Select cf/org/space in create service instance stepper mentions app #2313
  • Adding a space scoped service should not show org/space selection step #2311
  • Front-end unit tests are unreliable in Travis #2308
  • Not all backend tests are run #2300
  • Log Stream token refresh does not work #2299
  • Marketplace: Service Broker card should be hidden if the broker isn't returned by API #2279
  • Endpoint Users are not refetched when an endpoint is reconnected as a different user. #2274
  • Marketplace service cards tags list fails to expand #2263
  • App bound service is shown in services to bind to list #2253
  • Error response handling is broken #2242
  • Investigate issue with space-scoped services being returned incorrectly by the List Services for Space request #2240
  • App Log Stream shows Connecting.... for apps that aren't running #2235
  • Map Existing Routes: Sort by apps attached is broken #2210
  • Application: OFFLINE WHILE UPDATING state only allows the delete action. #2208
  • Cf/Org/Space filters are not updating on endpoint change #2162
  • Component effects are cropped in steppers #2116
  • Cloud Foundry orgs and space views contain multiple app-headers #2051
  • 2nd row of tabs sometimes disappears #2005
  • Instances tab shows Unknown when scaling (with crashed app) #2002
  • Console setup improvements #2 #1974
  • Services page does not update after connecting/disconnected an SCF #1973
  • White bar flashes at top of page on Cloud Foundry page #1963
  • Show service type in service wall card #2315
  • Show space name in space broker card #2312
  • Add confirmation modals where required #2257
  • Add git commit id and whether user is an admin on the about page #2246
  • Update base images for git vulnerability CVE 2018-11235 #2241
  • Update service steppers following async stepper changes #2234
  • CF Permissions - Apply to user management #2226
  • CF Permissions - Apply to services #2225
  • CF Permissions - Apply to App Wall + Summary #2224
  • V1 e2e fix #2316 (nwmac)

08 June 2018

The team have been working on the following issues and PRs this week:

  • Front-end unit tests are unreliable in Travis #3208 - we're seeing a lot of problems with the front-end unit tests when running in Travis - we're continuing to dig into this issue to understand what the cause is, since this is affecting reliability of PR gate checks.

  • Services permissions #2284 - wiring the user permissions service into the Service UI to ensure users are only presented with actions that they are permitted to perform.

  • Allow metrics endpoint token to be shared #2283 - adding support for the admin user to connect to a Prometheus metrics endpoint and then make that connection available to all users. Note that non-admins can only see metrics for applications that they have permission to view.

  • Show whether user is an admin on the about page #2306 - we now indicate on the about page if the current user is an administrator of Stratos.

  • Add Permissions to CF Users tables #2291 - wired in the user permissions service into the Cloud Foundry user management UI.

  • Wire in actions to app state #2288 - actions on the application view now use the same rules as in V1 to determine which actions should be shown based on the current application state.

  • Quicker e2e tests for PRs #2273 - changed the way e2e tests run for PRs. They will now use a quicker local deployment rather than a full deployment in docker.

  • Only show add and deploy buttons when there is at least 1 connected CF #2285 - we now only show the add and deploy buttons on the application wall when there is a Cloud Foundry available.

  • Fetch cf users when not cf admin #2282 - ensuring that we use different APIs call when the user is not an admin in order to retrieve the data to display for the user list.

  • Hide service broker card if broker information isn't available #2287 - we now hide the service broker card if we can not retrieve the broker metadata.

  • Only allow password change if user has password.write scope #2278 - user is now only presented with the option to change their password if they have permission to do so.

  • Backend logging improvements #2267 - first round of tidy up to the back-end logging, including not logging an error when verifying the user's seesion when they don't have a valid session.

  • Use local fonts #2260 - all fonts are now served up by the app itself to allow air-gapped deployment.

  • Endpoint confirmation modals #2258 - added confirmation modals when disconnecting or un-registering and endpoint.

  • Added theming section to developer guide readme #2249 - added documentation on how theming is done for Stratos.

  • Update permissions when when entities are updated #2221 - we now ensure that permissions are updated when endpoints (and other entities) are updated in Stratos.

01 June 2018

The team have been working on the following issues and PRs this week:

  • Upgrade to Angular 6 #2227 - Completed work and testing. Will merge early next week.

  • Edit service instance from Services Wall #2233 - Added ability to edit an existing service instance.

  • E2E Tests #1523 - Continuing to extend E2E test suite.

  • Fix compression issue #2248 - Fixed an issue when Stratos accessed a Cloud Foundry instance with gzip compression enabled. Thanks to everyone for their help with this one.

  • Fix App SSH (Broken when auth and token endpoints are different) #2250 - Fixed an issue with Application SSH for some CF deplyoments.

  • Fix application issue on reload when served by backend #2238 - Fixed an issue where refreshing the browser on application pages resulted in a 404 (when deployed via cf push)

25 May 2018

The team have been working on the following issues and PRs this week:

  • Upgrade to Angular 6 #2227

  • Handle async request progress/success/failure in modals #2223 - Improving busy state and error feedback in modals - e.g. when creating an application, creating a space etc

  • Service Summary tab #2219 - add a summary tab to the view for a service, to show summary metadata

  • Add support for back-end custom plugins #2217

  • Apply user permissions to CF pages (2) #2212 - Completion of work to wire in user permissions into the Cloud Foundry view

18 May 2018

The team have been working on the following issues and PRs this week:

  • User permissions #2147 - adding in the framework to control UI elements based on the user's permissions

  • Apply user permissions to CF pages #2198 - appropriately show the CF actions a user can perform based on their permissions

  • Service instances view #2074 - adding a view to show service instances

  • Services Wall: Create Services instance #2163 - adding support for creating service instances from the service marketplace view

  • App Services tab: Allow user to bind a service instance #2188

  • E2E Tests and E2E Test setup improvements #2183

  • Add support for Angular XSRF protection #2153 - adding support for the Angular XSRF protection mechanism

  • Remove deprecated API & Add confirmation dialogs when detaching/removing service bindings #2193

11 May 2018

The work to get V2 to the same level of functionality as V1 is going well and we're nearing completion - the team have been working on the following issues and PRs this week:

  • Add restart app button #2140 - adding restart action to applications

  • CF Push: Bump up memory further #2135 - increase memory when pushing to work around the memory-hungry Angular compiler

  • Service instances view #2074 - adding a view to show service instances

  • User permissions #2147 - adding in the framework to control UI elements based on the user's permissions

  • Customizations #2133 - initial support for customizing Stratos (theme etc)

  • E2E Tests #1523 - putting in place the E2E framework for V2, getting this working in Travis and porting over the V1 Endpoints tests.

  • Delete App should show dependencies and allow optional deletion #2044 - when deleting an application the user is shown the application dependencies (routes, service instances) and is able to delete these with the application or leave them in place for use by other applications

  • Cloud Foundry: Manage Users #1541 - re-introducing the equivalent features that V1 has allowing user to manage user roles across Cloud Foundry

4 May 2018

The team have been working on the following issues and PRs this week:

  • E2E Tests #1523 - putting in place the E2E framework for V2, getting this working in Travis and porting over the V1 Endpoints tests.

  • Delete App should show dependencies and allow optional deletion #2044 - when deleting an application the user is shown the application dependencies (routes, service instances) and is able to delete these with the application or leave them in place for use by other applications

  • Cloud Foundry: Manage Users #1541 - re-introducing the equivalent features that V1 has allowing user to manage user roles across Cloud Foundry

  • Implement Create Service Instance #2043 - adding support for creating service instances

  • Service Instance creation: Support space-scoped broker provided plans #2111

  • Make Service Instance creation wizard service plan visibility aware #2109

  • Return better error information from API passthroughs #2084

27 April 2018

The team have been working on the following issues this week:

  • GitHub tab/deploy updates #2067 - When deploying an application from GitHub, we now allow the user to select a commit from their selected branch. When viewing the GitHub tab of an application, the user can see the list of commits and update the application from a different commit on the branch.

  • Deploy App: Add support for an archive file or local folder #2040 - In addition to Git deployment, users can now browse to a local application archive file or folder and deploy using that.

  • User Profile: Implement edit and password change as per V1 #2062 - Users can now edit their profile metadata and change their password.

  • Create & List Service Instances - #2086 - adding the ability to view and create Service Instances.

  • Delete App should show dependencies and allow optional deletion #2044 - when deleting and application the user is shown the application dependencies(routes, service instances) and is able to delete these with the application or leave them in place for use by other applications

  • Cloud Foundry: Manage Users #1541 - re-introducing the equivalent features that V1 has allowing user to manage user roles across Cloud Foundry

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/docs/talks/index.html b/website/site-dist/docs/talks/index.html new file mode 100644 index 0000000000..695226ba60 --- /dev/null +++ b/website/site-dist/docs/talks/index.html @@ -0,0 +1,33 @@ + + + + + + +Talks and Presentations | STRATOS + + + + + + + + + + + + +
+

Talks and Presentations

Coming soon

+ + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/ed4459e0.2c80842d.js b/website/site-dist/ed4459e0.2c80842d.js new file mode 100644 index 0000000000..e265d6d3f2 --- /dev/null +++ b/website/site-dist/ed4459e0.2c80842d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{139:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return a})),n.d(t,"metadata",(function(){return s})),n.d(t,"rightToc",(function(){return c})),n.d(t,"default",(function(){return l}));var i=n(2),o=n(6),r=(n(0),n(149)),a={id:"contributing",title:"Contributing to Stratos",sidebar_label:"Contributing to Stratos"},s={id:"guides/contribution/contributing",isDocsHomePage:!1,title:"Contributing to Stratos",description:"Reporting issues",source:"@site/docs/guides/contribution/contributing.md",permalink:"/docs/guides/contribution/contributing",editUrl:"https://github.com/cloudfoundry/stratos/edit/master/website/docs/guides/contribution/contributing.md",sidebar_label:"Contributing to Stratos",sidebar:"docs",previous:{title:"Configuring Single Sign On",permalink:"/docs/advanced/sso"},next:{title:"Developing the Stratos Console",permalink:"/docs/developer/introduction"}},c=[{value:"Reporting issues",id:"reporting-issues",children:[]},{value:"Check for assigned people",id:"check-for-assigned-people",children:[]},{value:"Sign your work",id:"sign-your-work",children:[]}],u={rightToc:c};function l(e){var t=e.components,n=Object(o.a)(e,["components"]);return Object(r.b)("wrapper",Object(i.a)({},u,n,{components:t,mdxType:"MDXLayout"}),Object(r.b)("h2",{id:"reporting-issues"},"Reporting issues"),Object(r.b)("p",null,"Before reporting an issue, please check whether it has already been reported\n",Object(r.b)("a",Object(i.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues"}),"here"),". If this is the case, please:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Read all the comments to confirm that it's the same issue you're having."),Object(r.b)("li",{parentName:"ul"},'Refrain from adding "same thing here" or "+1" comments. Just hit the\n"subscribe" button to get notifications for this issue.'),Object(r.b)("li",{parentName:"ul"},"Add a comment only if you can provide helpful information that has not been\nprovided in the discussion yet.")),Object(r.b)("p",null,"If you want to report a ",Object(r.b)("strong",{parentName:"p"},"new issue"),", please ensure you give as much detail\nas possible about your setup/environment and provide sufficient steps\nfor the issue to be easily reproduced."),Object(r.b)("h2",{id:"check-for-assigned-people"},"Check for assigned people"),Object(r.b)("p",null,"We use Github Issues for submitting known issues (e.g. bugs, features,\netc.). Some issues will have someone assigned, meaning that there's already\nsomeone that takes responsibility for fixing the issue. This is not done to\ndiscourage contributions, rather to not step in the work that has already been\ndone by the assignee. If you want to work on a known issue with someone already\nassigned to it, please contact the assignee first (e.g. by\nmentioning the assignee in a new comment on the specific issue). This way you\ncan contribute with ideas, or even with code if the assignee decides that you\ncan step in."),Object(r.b)("p",null,"If you plan to work on a non assigned issue, please add a comment on the issue\nto prevent duplicated work."),Object(r.b)("h2",{id:"sign-your-work"},"Sign your work"),Object(r.b)("p",null,"The sign-off is a simple line at the end of the explanation for the patch. Your\nsignature certifies that you wrote the patch or otherwise have the right to pass\nit on as an open-source patch. The rules are pretty simple: if you can certify\nthe below (from ",Object(r.b)("a",Object(i.a)({parentName:"p"},{href:"http://developercertificate.org/"}),"developercertificate.org"),"):"),Object(r.b)("pre",null,Object(r.b)("code",Object(i.a)({parentName:"pre"},{}),"Developer Certificate of Origin\nVersion 1.1\n\nCopyright (C) 2004, 2006 The Linux Foundation and its contributors.\n660 York Street, Suite 102,\nSan Francisco, CA 94110 USA\n\nEveryone is permitted to copy and distribute verbatim copies of this\nlicense document, but changing it is not allowed.\n\nDeveloper's Certificate of Origin 1.1\n\nBy making a contribution to this project, I certify that:\n\n(a) The contribution was created in whole or in part by me and I\n have the right to submit it under the open source license\n indicated in the file; or\n\n(b) The contribution is based upon previous work that, to the best\n of my knowledge, is covered under an appropriate open source\n license and I have the right under that license to submit that\n work with modifications, whether created in whole or in part\n by me, under the same open source license (unless I am\n permitted to submit under a different license), as indicated\n in the file; or\n\n(c) The contribution was provided directly to me by some other\n person who certified (a), (b) or (c) and I have not modified\n it.\n\n(d) I understand and agree that this project and the contribution\n are public and that a record of the contribution (including all\n personal information I submit with it, including my sign-off) is\n maintained indefinitely and may be redistributed consistent with\n this project or the open source license(s) involved.\n")),Object(r.b)("p",null,"Then you just add a line to every git commit message:"),Object(r.b)("pre",null,Object(r.b)("code",Object(i.a)({parentName:"pre"},{}),"Signed-off-by: Joe Smith \n")),Object(r.b)("p",null,"Use your real name (sorry, no pseudonyms or anonymous contributions.)"),Object(r.b)("p",null,"If you set your ",Object(r.b)("inlineCode",{parentName:"p"},"user.name")," and ",Object(r.b)("inlineCode",{parentName:"p"},"user.email")," git configs, you can sign your\ncommit automatically with ",Object(r.b)("inlineCode",{parentName:"p"},"git commit -s"),"."))}l.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return p})),n.d(t,"b",(function(){return h}));var i=n(0),o=n.n(i);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function s(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=o.a.createContext({}),l=function(e){var t=o.a.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},p=function(e){var t=l(e.components);return o.a.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},b=o.a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,a=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),p=l(n),b=i,h=p["".concat(a,".").concat(b)]||p[b]||d[b]||r;return n?o.a.createElement(h,s(s({ref:t},u),{},{components:n})):o.a.createElement(h,s({ref:t},u))}));function h(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,a=new Array(r);a[0]=b;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:i,a[1]=s;for(var u=2;u=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var p=a.a.createContext({}),s=function(e){var t=a.a.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},b=function(e){var t=s(e.components);return a.a.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},d=a.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,c=e.originalType,i=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),b=s(r),d=n,m=b["".concat(i,".").concat(d)]||b[d]||u[d]||c;return r?a.a.createElement(m,o(o({ref:t},p),{},{components:r})):a.a.createElement(m,o({ref:t},p))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var c=r.length,i=new Array(c);i[0]=d;var o={};for(var l in t)hasOwnProperty.call(t,l)&&(o[l]=t[l]);o.originalType=e,o.mdxType="string"==typeof e?e:n,i[1]=o;for(var p=2;p',\n matIcon: ''\n }\n")),Object(l.b)("p",null,"Where ",Object(l.b)("inlineCode",{parentName:"p"},"")," is the text label to show in the side navigation and ",Object(l.b)("inlineCode",{parentName:"p"},"<ICON NAME>")," is the icon to use."),Object(l.b)("p",null,"You should place your route declaration in a module named ",Object(l.b)("inlineCode",{parentName:"p"},"CustomRoutingModule")," in the file ",Object(l.b)("inlineCode",{parentName:"p"},"custom-src/frontend/app/custom/custom-routing.module.ts"),"."),Object(l.b)("p",null,"An example routing module would be:"),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"import { NgModule } from '@angular/core';\nimport { Routes, RouterModule } from '@angular/router';\n\nconst customRoutes: Routes = [{\n path: 'example',\n loadChildren: 'app/custom/nav-extension/nav-extension.module#NavExtensionModule',\n data: {\n stratosNavigation: {\n text: 'Example',\n matIcon: 'extension'\n }\n }\n}];\n\n@NgModule({\n imports: [\n RouterModule.forRoot(customRoutes),\n ],\n declarations: []\n})\nexport class CustomRoutingModule { }\n")),Object(l.b)("p",null,"This approach ensures that the Angular compiler creates a separate chunk for the extension at compile time."),Object(l.b)("h3",{id:"custom-tabs"},"Custom Tabs"),Object(l.b)("p",null,"Tabs can be added to the following views in Stratos:"),Object(l.b)("ul",null,Object(l.b)("li",{parentName:"ul"},"The Application view that shows the detail of an application"),Object(l.b)("li",{parentName:"ul"},"The Cloud Foundry view that shows detail for a Cloud Foundry"),Object(l.b)("li",{parentName:"ul"},"The Cloud Foundry Org view that shows detail for a Cloud Foundry organization"),Object(l.b)("li",{parentName:"ul"},"The Cloud Foundry Space view that shows detail for a Cloud Foundry space")),Object(l.b)("p",null,"For example:"),Object(l.b)("p",null,Object(l.b)("img",Object(o.a)({parentName:"p"},{src:"../images/extensions/app-tab-example.png",alt:"Example Application tab extension"}))),Object(l.b)("p",null,"The approach for all of these is the same:"),Object(l.b)("ol",null,Object(l.b)("li",{parentName:"ol"},"Create a new component that will provide the tab contents"),Object(l.b)("li",{parentName:"ol"},"Ensure that your component is included in the ",Object(l.b)("inlineCode",{parentName:"li"},"EntryComponent")," section of your custom module"),Object(l.b)("li",{parentName:"ol"},"Decorate the component with the ",Object(l.b)("inlineCode",{parentName:"li"},"StratosTab")," decorator, for example:")),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"@StratosTab({\n type: StratosTabType.Application,\n label: '<LABEL>',\n link: '<LINK>'\n})\n")),Object(l.b)("p",null,"Where:"),Object(l.b)("ul",null,Object(l.b)("li",{parentName:"ul"},"< TYPE > indicates where the tab should appear and can be:",Object(l.b)("ul",{parentName:"li"},Object(l.b)("li",{parentName:"ul"},"StratosTabType.Application - Application View"),Object(l.b)("li",{parentName:"ul"},"StratosTabType.CloudFoundry - Cloud Foundry view"),Object(l.b)("li",{parentName:"ul"},"StratosTabType.CloudFoundryOrg - Cloud Foundry Org view"),Object(l.b)("li",{parentName:"ul"},"StratosTabType.CloudFoundrySpace - Cloud Foundry Space view"))),Object(l.b)("li",{parentName:"ul"},"< LABEL > is the text label to use for the tab"),Object(l.b)("li",{parentName:"ul"},"< LINK > is the name to use for the route (this must only contain characters permitted in URLs)")),Object(l.b)("p",null,"An example is included in the file ",Object(l.b)("inlineCode",{parentName:"p"},"examples/custom-src/frontend/app/custom/app-tab-extension"),"."),Object(l.b)("h3",{id:"custom-actions"},"Custom Actions"),Object(l.b)("p",null,"Actions can be added to the following views in Stratos:"),Object(l.b)("ul",null,Object(l.b)("li",{parentName:"ul"},"The Application Wall view that shows all applications"),Object(l.b)("li",{parentName:"ul"},"The Application view that shows the detail of an application"),Object(l.b)("li",{parentName:"ul"},"The Cloud Foundry view that shows detail for a Cloud Foundry"),Object(l.b)("li",{parentName:"ul"},"The Cloud Foundry Org view that shows detail for a Cloud Foundry organization"),Object(l.b)("li",{parentName:"ul"},"The Cloud Foundry Space view that shows detail for a Cloud Foundry space"),Object(l.b)("li",{parentName:"ul"},"The Endpoints view that shows all endpoints")),Object(l.b)("p",null,"An action is a icon button that appears at the top-right of a View. For example:"),Object(l.b)("p",null,Object(l.b)("img",Object(o.a)({parentName:"p"},{src:"../images/extensions/appwall-action-example.png",alt:"Example Application action extension"}))),Object(l.b)("p",null,"The approach for all of these is the same:"),Object(l.b)("ol",null,Object(l.b)("li",{parentName:"ol"},"Create a new component that will provide the contents to show when the action is clicked"),Object(l.b)("li",{parentName:"ol"},"Ensure that your component is included in the ",Object(l.b)("inlineCode",{parentName:"li"},"EntryComponent")," section of your custom module"),Object(l.b)("li",{parentName:"ol"},"Decorate the component with the ",Object(l.b)("inlineCode",{parentName:"li"},"StratosAction")," decorator, for example:")),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"@StratosAction({\n type: StratosActionType.Applications,\n label: '<LABEL>',\n link: '<LINK>',\n icon: '<ICON>\n})\n")),Object(l.b)("p",null,"Where:"),Object(l.b)("ul",null,Object(l.b)("li",{parentName:"ul"},"< TYPE > indicates where the action should appear and can be:",Object(l.b)("ul",{parentName:"li"},Object(l.b)("li",{parentName:"ul"},"StratosActionType.Applications - Application Wall View"),Object(l.b)("li",{parentName:"ul"},"StratosActionType.Application - Application View"),Object(l.b)("li",{parentName:"ul"},"StratosActionType.CloudFoundry - Cloud Foundry view"),Object(l.b)("li",{parentName:"ul"},"StratosActionType.CloudFoundryOrg - Cloud Foundry Org view"),Object(l.b)("li",{parentName:"ul"},"StratosActionType.CloudFoundrySpace - Cloud Foundry Space view"),Object(l.b)("li",{parentName:"ul"},"StratosActionType.Endpoints - Endpoints view"))),Object(l.b)("li",{parentName:"ul"},"< ICON > is the icon to show"),Object(l.b)("li",{parentName:"ul"},"< LABEL > is the text label to use for the tooltip of the icon (optional)"),Object(l.b)("li",{parentName:"ul"},"< LINK > is the name to use for the route (this must only contain characters permitted in URLs)")),Object(l.b)("p",null,"An example is included in the file ",Object(l.b)("inlineCode",{parentName:"p"},"examples/custom-src/frontend/app/custom/app-action-extension"),"."),Object(l.b)("h2",{id:"example-adding-a-custom-tab"},"Example: Adding a Custom Tab"),Object(l.b)("p",null,"In this example, we will walk through extending the Stratos front-end."),Object(l.b)("p",null,"This walk-through assumes that you have installed the Angular CLI globally - this can be done with ",Object(l.b)("inlineCode",{parentName:"p"},"npm install -g @angular/cli"),"."),Object(l.b)("h3",{id:"create-a-new-module"},"Create a new module"),Object(l.b)("p",null,"First, create the custom-src folder structure - from the top-level of the Stratos repository run:"),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"mkdir -p custom-src/frontend/app/custom\nmkdir -p custom-src/frontend/assets/custom\n")),Object(l.b)("p",null,"Next, run the customize task:"),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"npm run customize\n")),Object(l.b)("p",null,"This will symlink our custom folder into the Stratos application source folder."),Object(l.b)("p",null,"Next, use the Angular CLI to create the root module for our custom code with:"),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"ng generate module custom\n")),Object(l.b)("p",null,"This create a new Angular module ",Object(l.b)("inlineCode",{parentName:"p"},"CustomModule"),"."),Object(l.b)("p",null,"Run the customize script again, now that that we have created the custom module with:"),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"npm run customize\n")),Object(l.b)("h3",{id:"create-a-new-component-for-our-tab"},"Create a new Component for our Tab"),Object(l.b)("p",null,"Create a new Angular component with the CLI:"),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"ng generate component custom/example-tab-extension\n")),Object(l.b)("h3",{id:"add-decorator-to-make-this-component-an-extension"},"Add Decorator to make this Component an Extension"),Object(l.b)("p",null,"In a text editor, open the file:"),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"src/frontend/app/custom/example-tab-extension/example-tab-extension.component.ts\n")),Object(l.b)("p",null,"Add the following decorator to the component at the top of the file:"),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"import { StratosTab, StratosTabType } from '../../core/extension/extension-service';\n\n@StratosTab({\n type: StratosTabType.Application,\n label: 'Example App Tab',\n link: 'example'\n})\n")),Object(l.b)("p",null,"The file should now look like this:"),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"import { Component, OnInit } from '@angular/core';\nimport { StratosTab, StratosTabType } from '../../core/extension/extension-service';\n\n@StratosTab({\n type: StratosTabType.Application,\n label: 'Example App Tab',\n link: 'example'\n})\n@Component({\n selector: 'app-example-tab-extension',\n templateUrl: './example-tab-extension.component.html',\n styleUrls: ['./example-tab-extension.component.scss']\n})\nexport class ExampleTabExtensionComponent implements OnInit {\n\n constructor() { }\n\n ngOnInit() {\n }\n\n}\n")),Object(l.b)("p",null,"Save the file."),Object(l.b)("h3",{id:"mark-the-component-as-an-entry-component"},"Mark the component as an entry component"),Object(l.b)("p",null,"The last thing we need to do is to mark our Extension component as an entry component."),Object(l.b)("p",null,"To do this, in a text editor, open the file ",Object(l.b)("inlineCode",{parentName:"p"},"src/frontend/app/custom/custom.module.ts")," and add the entry components section so it looks like this:"),Object(l.b)("pre",null,Object(l.b)("code",Object(o.a)({parentName:"pre"},{}),"@NgModule({\n imports: [\n CommonModule\n ],\n declarations: [ExampleTabExtensionComponent],\n entryComponents: [ExampleTabExtensionComponent]\n})\nexport class CustomModule { }\n")),Object(l.b)("h3",{id:"run-it"},"Run it"),Object(l.b)("p",null,"You should now be able to run Stratos locally and see this new tab on the application page for an application - as illustrated below:"),Object(l.b)("p",null,Object(l.b)("img",Object(o.a)({parentName:"p"},{src:"../images/extensions/tab-example.png",alt:"Example tab extension"}))))}s.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return b})),n.d(t,"b",(function(){return d}));var o=n(0),a=n.n(o);function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){l(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function c(e,t){if(null==e)return{};var n,o,a=function(e,t){if(null==e)return{};var n,o,a={},l=Object.keys(e);for(o=0;o<l.length;o++)n=l[o],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(o=0;o<l.length;o++)n=l[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=a.a.createContext({}),s=function(e){var t=a.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},b=function(e){var t=s(e.components);return a.a.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},m=a.a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,l=e.originalType,r=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),b=s(n),m=o,d=b["".concat(r,".").concat(m)]||b[m]||u[m]||l;return n?a.a.createElement(d,i(i({ref:t},p),{},{components:n})):a.a.createElement(d,i({ref:t},p))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var l=n.length,r=new Array(l);r[0]=m;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i.mdxType="string"==typeof e?e:o,r[1]=i;for(var p=2;p<l;p++)r[p]=n[p];return a.a.createElement.apply(null,r)}return a.a.createElement.apply(null,n)}m.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/website/site-dist/f85084f8.70ed67c0.js b/website/site-dist/f85084f8.70ed67c0.js new file mode 100644 index 0000000000..ce86e191e2 --- /dev/null +++ b/website/site-dist/f85084f8.70ed67c0.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[41],{142:function(e,t,a){"use strict";a.r(t),a.d(t,"frontMatter",(function(){return i})),a.d(t,"metadata",(function(){return s})),a.d(t,"rightToc",(function(){return l})),a.d(t,"default",(function(){return c}));var n=a(2),r=a(6),o=(a(0),a(149)),i={},s={id:"status_updates",isDocsHomePage:!1,title:"status_updates",description:"Status Updates",source:"@site/docs/status_updates.md",permalink:"/docs/status_updates",editUrl:"https://github.com/cloudfoundry/stratos/edit/master/website/docs/status_updates.md"},l=[{value:"12 April 2019",id:"12-april-2019",children:[]},{value:"5 April 2019",id:"5-april-2019",children:[]},{value:"22 March 2019",id:"22-march-2019",children:[]},{value:"15 March 2019",id:"15-march-2019",children:[]},{value:"8 March 2019",id:"8-march-2019",children:[]},{value:"1 March 2019",id:"1-march-2019",children:[]},{value:"22 February 2019",id:"22-february-2019",children:[]},{value:"15 February 2019",id:"15-february-2019",children:[]},{value:"8 February 2019",id:"8-february-2019",children:[]},{value:"1 February 2019",id:"1-february-2019",children:[]},{value:"25 January 2019",id:"25-january-2019",children:[]},{value:"18 January 2019",id:"18-january-2019",children:[]},{value:"11 January 2019",id:"11-january-2019",children:[]},{value:"21st December 2018",id:"21st-december-2018",children:[]},{value:"7th December 2018",id:"7th-december-2018",children:[]},{value:"30th November 2018",id:"30th-november-2018",children:[]},{value:"23rd November 2018",id:"23rd-november-2018",children:[]},{value:"16th November 2018",id:"16th-november-2018",children:[]},{value:"9th November 2018",id:"9th-november-2018",children:[]},{value:"2nd November 2018",id:"2nd-november-2018",children:[]},{value:"26th October 2018",id:"26th-october-2018",children:[]},{value:"19th October 2018",id:"19th-october-2018",children:[]},{value:"12th October 2018",id:"12th-october-2018",children:[]},{value:"5th October 2018",id:"5th-october-2018",children:[]},{value:"28th September 2018",id:"28th-september-2018",children:[]},{value:"21st September 2018",id:"21st-september-2018",children:[]},{value:"14th September 2018",id:"14th-september-2018",children:[]},{value:"7th September 2018",id:"7th-september-2018",children:[]},{value:"31st August 2018",id:"31st-august-2018",children:[]},{value:"24th August 2018",id:"24th-august-2018",children:[]},{value:"17th August 2018",id:"17th-august-2018",children:[]},{value:"10th August 2018",id:"10th-august-2018",children:[]},{value:"3 August 2018",id:"3-august-2018",children:[]},{value:"27 July 2018",id:"27-july-2018",children:[]},{value:"20 July 2018",id:"20-july-2018",children:[]},{value:"13 July 2018",id:"13-july-2018",children:[]},{value:"06 July 2018",id:"06-july-2018",children:[]},{value:"29 June 2018",id:"29-june-2018",children:[]},{value:"22 June 2018",id:"22-june-2018",children:[]},{value:"15 June 2018",id:"15-june-2018",children:[]},{value:"08 June 2018",id:"08-june-2018",children:[]},{value:"01 June 2018",id:"01-june-2018",children:[]},{value:"25 May 2018",id:"25-may-2018",children:[]},{value:"18 May 2018",id:"18-may-2018",children:[]},{value:"11 May 2018",id:"11-may-2018",children:[]},{value:"4 May 2018",id:"4-may-2018",children:[]},{value:"27 April 2018",id:"27-april-2018",children:[]}],b={rightToc:l};function c(e){var t=e.components,a=Object(r.a)(e,["components"]);return Object(o.b)("wrapper",Object(n.a)({},b,a,{components:t,mdxType:"MDXLayout"}),Object(o.b)("h1",{id:"status-updates"},"Status Updates"),Object(o.b)("p",null,"Weekly status updates are published here."),Object(o.b)("h2",{id:"12-april-2019"},"12 April 2019"),Object(o.b)("p",null,"This week the Stratos team has been..."),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Presenting Stratos v2.4 features to the community in the latest project update"),Object(o.b)("li",{parentName:"ul"},"Working towards phase two of the extension project."),Object(o.b)("li",{parentName:"ul"},"Finishing off the remove roles from cf user feature."),Object(o.b)("li",{parentName:"ul"},"Finishing off adding an optional 'connect' step to the register endpoint stepper."),Object(o.b)("li",{parentName:"ul"},"Reviewing and shepherding PRs into master, minor bug fixes.")),Object(o.b)("h2",{id:"5-april-2019"},"5 April 2019"),Object(o.b)("p",null,"This week the Stratos team have mostly been ..."),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Improving e2e reliability and merging existing PRs."),Object(o.b)("li",{parentName:"ul"},"Improving the create/deploy app flow. Users will now only be presented with a single button to start the flow. Their first step is to decide where the source for the app will come from (github, gitlab, locally, etc) or to create without source."),Object(o.b)("li",{parentName:"ul"},"Removing the endpoints page when there's no persistent storage. This is now on par with the home/favourites page."),Object(o.b)("li",{parentName:"ul"},"Adding an option that will allow the user to stay signed in to the console (if option is checked and the page remains visible)."),Object(o.b)("li",{parentName:"ul"},"Starting working towards the ability to remove all roles from a cf user with a single click (after confirmation)."),Object(o.b)("li",{parentName:"ul"},"Starting working towards an optional 'connect' step when registering an endpoint."),Object(o.b)("li",{parentName:"ul"},"Fixed a few minor trivial bugs")),Object(o.b)("h2",{id:"22-march-2019"},"22 March 2019"),Object(o.b)("p",null,"This week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Work continues to complete the addition of support for Cloud Foundry User Provided Services. This is almost done. A few small issues and corner-cases cropped up which we have been working on."),Object(o.b)("li",{parentName:"ul"},"Added support for slide-in help content and wired this into the endpoint connection dialog"),Object(o.b)("li",{parentName:"ul"},"We continued to refine the visual presentation of endpoints within Stratos")),Object(o.b)("h2",{id:"15-march-2019"},"15 March 2019"),Object(o.b)("p",null,"This week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Enhancing the endpoint registration view to use a tile selector"),Object(o.b)("li",{parentName:"ul"},"Updating our docs on our use cases and requirements for the Cloud Foundry V3 API")),Object(o.b)("h2",{id:"8-march-2019"},"8 March 2019"),Object(o.b)("p",null,"This week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Added a card view to the endpoints view"),Object(o.b)("li",{parentName:"ul"},"Continued to refine the support for User Provided Service Instances"),Object(o.b)("li",{parentName:"ul"},"Working on support to allow list views to show different entity types in the same list"),Object(o.b)("li",{parentName:"ul"},"Ensured features requiring persistence database are not enabled when using SQLite")),Object(o.b)("h2",{id:"1-march-2019"},"1 March 2019"),Object(o.b)("p",null,"This week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Updated the front-end code to use Angular 7 (in review)"),Object(o.b)("li",{parentName:"ul"},"Continued to add support for User Provided Service Instances"),Object(o.b)("li",{parentName:"ul"},"Reviewed, tweaked and merged our first phase of work on improving extensions support")),Object(o.b)("h2",{id:"22-february-2019"},"22 February 2019"),Object(o.b)("p",null,"This week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"The user invite feature has been reviewed and merged"),Object(o.b)("li",{parentName:"ul"},"Front-end code restructuring to support next phase of extensions work"),Object(o.b)("li",{parentName:"ul"},"Pre-work for update to Angular 7"),Object(o.b)("li",{parentName:"ul"},"Add support for User Provided Services"),Object(o.b)("li",{parentName:"ul"},"Updates to our documentation on our needs for the Cloud Foundry V3 API")),Object(o.b)("p",null,Object(o.b)("strong",{parentName:"p"},"Important:")),Object(o.b)("p",null,"Hello All - Two CVEs in Stratos were recently discovered - both are fixed in 2.3.0 - so we ",Object(o.b)("strong",{parentName:"p"},"encourage you to update")," to that latest version to address these issues. Both relate to the session cookie:"),Object(o.b)("p",null,Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://www.cloudfoundry.org/blog/cve-2019-3783/"}),"https://www.cloudfoundry.org/blog/cve-2019-3783/"),"\n",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://www.cloudfoundry.org/blog/cve-2019-3784/"}),"https://www.cloudfoundry.org/blog/cve-2019-3784/")),Object(o.b)("p",null,Object(o.b)("strong",{parentName:"p"},"Deployment Survey")),Object(o.b)("p",null,"We want to understand more about how everyone is deploying Stratos - so we can better support the most used deployment scenarios and (possibly) remove some of the deployment mechanisms that aren\u2019t being used - we\u2019ve got a quick survey we\u2019d love it if you could fill out: ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://www.surveymonkey.co.uk/r/MLXDMKG"}),"https://www.surveymonkey.co.uk/r/MLXDMKG")),Object(o.b)("h2",{id:"15-february-2019"},"15 February 2019"),Object(o.b)("p",null,"This week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"2.3.0 was Released!"),Object(o.b)("li",{parentName:"ul"},"The user Favourites feature has been reviewed and merged"),Object(o.b)("li",{parentName:"ul"},"We continue to fix and merge many of the outstanding PRs around User Favourites and Scalability"),Object(o.b)("li",{parentName:"ul"},"We spent half a day reviewing our next steps to re-structure the front-end code as part of our work towards the next phase of extensibility."),Object(o.b)("li",{parentName:"ul"},"We continue to improve the suite of automated deployment tests that run continuosuly")),Object(o.b)("h2",{id:"8-february-2019"},"8 February 2019"),Object(o.b)("p",null,"Release 2.3.0 is all ready to go and we will publish this on Monday."),Object(o.b)("p",null,"Otherwise, we've been working on:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Finishing a first version of the User Favourites feature"),Object(o.b)("li",{parentName:"ul"},"Finishing a first version of the User Invitation feature"),Object(o.b)("li",{parentName:"ul"},"Investigating possible security issue: ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/3385"}),"https://github.com/cloudfoundry/stratos/issues/3385")),Object(o.b)("li",{parentName:"ul"},"Updates to our extensions approach ")),Object(o.b)("h2",{id:"1-february-2019"},"1 February 2019"),Object(o.b)("p",null,"We are looking to release 2.3.0 next week having completed testing."),Object(o.b)("p",null,"Work has otherwise continued on four tracks:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Closing out existing PRs"),Object(o.b)("li",{parentName:"ul"},"Finishing a first version of the User Favourites feature"),Object(o.b)("li",{parentName:"ul"},"Finishing a first version of the User Invitation feature"),Object(o.b)("li",{parentName:"ul"},"Improving test automation")),Object(o.b)("h2",{id:"25-january-2019"},"25 January 2019"),Object(o.b)("p",null,"This week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Published a release candidate for Stratos 2.3.0 which we continue to test"),Object(o.b)("li",{parentName:"ul"},"Worked to update a few outstanding PRs - we are aiming to close out some of the remaining PRs this sprint, ahead of a re-org of our front-end code to better support extensions to Stratos in the future"),Object(o.b)("li",{parentName:"ul"},"Continued to refine the User Favourites feature"),Object(o.b)("li",{parentName:"ul"},"Worked to add the ability to invite a user into a Cloud Foundry organisation"),Object(o.b)("li",{parentName:"ul"},"Continued to improve the reliability of automated deployment tests in Jenkins")),Object(o.b)("h2",{id:"18-january-2019"},"18 January 2019"),Object(o.b)("p",null,"We created a test release of 2.3.0 and identified a number of issues to be resolved for release."),Object(o.b)("p",null,"The remainder of this week was spent fixing the issues identified."),Object(o.b)("p",null,"A 2.3.0 Release Candidate will be published later today or on Monday of next week."),Object(o.b)("p",null,"We hope to finish testing and publish the 2.3.0 release next week."),Object(o.b)("p",null,"The 2.3.0 Change Log has been updated and is available ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/blob/master/CHANGELOG.md"}),"here")),Object(o.b)("h2",{id:"11-january-2019"},"11 January 2019"),Object(o.b)("p",null,"Happy New Year!"),Object(o.b)("p",null,"The focus of the week was in preparing 2.3.0 release:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"We reviewed, updated and merged over 20 outstanding PRs that were targeted at 2.3.0 release"),Object(o.b)("li",{parentName:"ul"},"We\u2019ve made some improvements to our Helm chart to the external service configuration"),Object(o.b)("li",{parentName:"ul"},"We\u2019ve tweaked our release process and updated and improved our Concourse release pipelines"),Object(o.b)("li",{parentName:"ul"},"Performed initial testing of 2.3.0 build")),Object(o.b)("p",null,"We expect to create a Release Candidate next for 2.3.0 so QA can kick the tyres as well."),Object(o.b)("p",null,"We\u2019re also looking at the roadmap for this year and planning our releases throughout 2019."),Object(o.b)("h2",{id:"21st-december-2018"},"21st December 2018"),Object(o.b)("p",null,"Rounding off our year, here's some highlights from the last few weeks."),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"User Favourites - Great progress has been made and we're almost ready to merge to master."),Object(o.b)("li",{parentName:"ul"},"Page Tabs & Side Nav Update - The horizontal tabs shown in sections such as Application, Cloud Foundry, Organisation, etc have found a smart new home in a side nav. For screenshots see PR #3289")),Object(o.b)("p",null,"PRs:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Add a routes list to the CF tabs, Routes Refactor & Route Bug Fixes (#3292)"),Object(o.b)("li",{parentName:"ul"},"Add deployment info for apps deployed via docker & fix info for local/archive apps (#3291)"),Object(o.b)("li",{parentName:"ul"},"Improve focus & tabbing (#3288)"),Object(o.b)("li",{parentName:"ul"},"Application Env Var fix & improvements (#3286)"),Object(o.b)("li",{parentName:"ul"},"Fix exception when navigating away from the first deploy app step (#3277)"),Object(o.b)("li",{parentName:"ul"},"Add service plan tab to service pages (#3275)"),Object(o.b)("li",{parentName:"ul"},"List Multifilter Improvements (don't show cloud foundry selector if there's only one connected) (#3270)"),Object(o.b)("li",{parentName:"ul"},"Update side nav logo with light version of new logo (#2921)"),Object(o.b)("li",{parentName:"ul"},"Hide app vars tab if user is not a space developer (#3247)"),Object(o.b)("li",{parentName:"ul"},"Show app chip list for space routes list bound apps (#3041)")),Object(o.b)("p",null,"Community PRs:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Fixes Async Service Provisioning Bug (#3090) (merged)"),Object(o.b)("li",{parentName:"ul"},"[autoscaler]"," add autoscaler tab in app page (#3266)")),Object(o.b)("h2",{id:"7th-december-2018"},"7th December 2018"),Object(o.b)("p",null,"The team are continuing to tackle some of the smaller issues form the backlog as well as the following two features:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"User Favorites - Allowing users to favorite Apps, Orgs, Spaces etc and to provide quick access to these items."),Object(o.b)("li",{parentName:"ul"},"Inviting Users - Support for inviting users to a Cloud Foundry system via email and to grant appropriate rights to an Org/Space")),Object(o.b)("p",null,"PRs:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Reduce size of Docker All-in-one image ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3261"}),"#","3261")),Object(o.b)("li",{parentName:"ul"},"Tidy up CLI login info ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3269"}),"#","3269")),Object(o.b)("li",{parentName:"ul"},"Add service provider name to marketplace service card ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3268"}),"#","3268")),Object(o.b)("li",{parentName:"ul"},"Add link to dashboard in service instance table ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3267"}),"#","3267")),Object(o.b)("li",{parentName:"ul"},"Add Org and Space status bar to Org/Space Cards ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3265"}),"#","3265")),Object(o.b)("li",{parentName:"ul"},"Helm port configuration improvements and unit tests ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3265"}),"#","3264")),Object(o.b)("li",{parentName:"ul"},"Add confirmation dialog to ",Object(o.b)("inlineCode",{parentName:"li"},"Restage")," app ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3263"}),"#","3263")),Object(o.b)("li",{parentName:"ul"},"Remove global manage apps link ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3259"}),"#","3259")),Object(o.b)("li",{parentName:"ul"},"Add user has roles filter to users tables ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3258"}),"#","3258"))),Object(o.b)("h2",{id:"30th-november-2018"},"30th November 2018"),Object(o.b)("p",null,"A quieter week for the Stratos team - with some out on vacation as we head towards the festive season."),Object(o.b)("p",null,"PRs this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Make the table multi actions more obvious ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3251"}),"#","3251")),Object(o.b)("li",{parentName:"ul"},"Hide app vars tab if user is not a space developer ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3247"}),"#","3247")),Object(o.b)("li",{parentName:"ul"},"Improve resilience of e2e tests ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3246"}),"#","3246")),Object(o.b)("li",{parentName:"ul"},"App Wall filter and sort controls size tweaks ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3243"}),"#","3243")),Object(o.b)("li",{parentName:"ul"},"Deploy App: Add notification toast ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3242"}),"#","3242"))),Object(o.b)("h2",{id:"23rd-november-2018"},"23rd November 2018"),Object(o.b)("p",null,"We've been continuing to test Stratos 2.2.0 and improving test automation and E2E test reliability."),Object(o.b)("p",null,"We've started to work through some of the GitHub issues - the focus for the next couple of sprints is to fix and close out some of the smaller issues and bugs."),Object(o.b)("p",null,"We're also working to improve the scalability of Stratos with large numbers of Apps/Orgs/Spaces/Users."),Object(o.b)("p",null,"PRs this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"App Deploy: Add Public GitLab Repository support ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3239"}),"#","3239")),Object(o.b)("li",{parentName:"ul"},"Fix CLI info formatting ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3237"}),"#","3237")),Object(o.b)("li",{parentName:"ul"},"Show better error message on login screen when account locked ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3235"}),"#","3235")),Object(o.b)("li",{parentName:"ul"},"Add Route: Use correct label for submit button ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3231"}),"#","3231")),Object(o.b)("li",{parentName:"ul"},"Fix for cancel broken on add route ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3228"}),"#","3228")),Object(o.b)("li",{parentName:"ul"},"Backend: Update to latest version of Echo Web Server ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3216"}),"#","3216")),Object(o.b)("li",{parentName:"ul"},"Show refresh button for latest modified application lists ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3213"}),"#","3213")),Object(o.b)("li",{parentName:"ul"},"Scalability: Handle large number of apps in cf dashboards ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3212"}),"#","3212")),Object(o.b)("li",{parentName:"ul"},"Support prometheus-boshrelease as a metrics endpoint ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3202"}),"#","3202")),Object(o.b)("li",{parentName:"ul"},"Fix alignment of arrow when no endpoints registered ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3234"}),"#","3234")),Object(o.b)("li",{parentName:"ul"},"Run customize when prebuild and log node and npm versions ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3232"}),"#","3232")),Object(o.b)("li",{parentName:"ul"},"Add stricter check for jetstream error object ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3223"}),"#","3223")),Object(o.b)("li",{parentName:"ul"},"Improve paginated/pagination action naming ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3218"}),"#","3218")),Object(o.b)("li",{parentName:"ul"},"Fix display of generic error bar ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3214"}),"#","3214")),Object(o.b)("li",{parentName:"ul"},"Only show + icon when we have at least one connected CF ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3211"}),"#","3211"))),Object(o.b)("h2",{id:"16th-november-2018"},"16th November 2018"),Object(o.b)("p",null,"This week the team has been working on:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Testing Stratos 2.2.0"),Object(o.b)("li",{parentName:"ul"},"Enabling Extensions to be published separately"),Object(o.b)("li",{parentName:"ul"},"Test automation"),Object(o.b)("li",{parentName:"ul"},"E2E Test reliability"),Object(o.b)("li",{parentName:"ul"},"Space service tidy up ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3197"}),"#","3197"))),Object(o.b)("h2",{id:"9th-november-2018"},"9th November 2018"),Object(o.b)("p",null,"This week the team has been:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Testing Stratos 2.2.0"),Object(o.b)("li",{parentName:"ul"},"Working towards enabling Extensions to be published separately"),Object(o.b)("li",{parentName:"ul"},"Updating developer documents: ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3184"}),"#","3184")),Object(o.b)("li",{parentName:"ul"},"Adding initial document for back-end plugins: ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3189"}),"#","3189")),Object(o.b)("li",{parentName:"ul"},"Fixed bug with deploying with folder upload: ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3191"}),"#","3191"))),Object(o.b)("h2",{id:"2nd-november-2018"},"2nd November 2018"),Object(o.b)("p",null,"This week we have mostly been:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Releasing Stratos 2.2.0. More details can be found at ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/releases/tag/2.2.0"}),"https://github.com/cloudfoundry/stratos/releases/tag/2.2.0"),". "),Object(o.b)("li",{parentName:"ul"},"Discussing integration of the Autoscaler (",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry-incubator/app-autoscaler"}),"https://github.com/cloudfoundry-incubator/app-autoscaler"),") UI (",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry-incubator/app-autoscaler-ui"}),"https://github.com/cloudfoundry-incubator/app-autoscaler-ui"),") into Stratos. We\u2019ve provided a first round of guidance to the Autoscaler team and are looking forward to the second round next week. The initial designs look great."),Object(o.b)("li",{parentName:"ul"},"Knowledge sharing activities revolving helm charts and concourse release pipelines")),Object(o.b)("h2",{id:"26th-october-2018"},"26th October 2018"),Object(o.b)("p",null,"The team were away attending a workshop this week."),Object(o.b)("p",null,"The only item of note is that we have now forked the go-flags package that was causing broken dependency issues for us and updated Stratos to use this package. This should allow us to avoid future issues with this package."),Object(o.b)("h2",{id:"19th-october-2018"},"19th October 2018"),Object(o.b)("p",null,"We are preparing for this month's 2.2.0 release which will be out towards the end of the month."),Object(o.b)("p",null,"Highlights for this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Extensions: Fix for side nav. Add initial docs ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3140"}),"#","3140")),Object(o.b)("li",{parentName:"ul"},"User menu improvements ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3136"}),"#","3136")),Object(o.b)("li",{parentName:"ul"},"Metrics: Show table of cell health state changes instead of chart ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3135"}),"#","3135")),Object(o.b)("li",{parentName:"ul"},"Metrics: Update app instance cell data when scaling up ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3133"}),"#","3133")),Object(o.b)("li",{parentName:"ul"},"Metrics: Ensure CF Cells info is shown for non cf admins ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3121"}),"#","3121")),Object(o.b)("li",{parentName:"ul"},"Add 'type text to continue' to confirmation modal ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3131"}),"#","3131")),Object(o.b)("li",{parentName:"ul"},"Delete App Stepper: Disable delete of routes and services that are bound to other app/s ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3129"}),"#","3129")),Object(o.b)("li",{parentName:"ul"},"Endpoints Table: Only show 'Admin' check icon for cf endpoints ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3132"}),"#","3132"))),Object(o.b)("h2",{id:"12th-october-2018"},"12th October 2018"),Object(o.b)("p",null,"The team have been preparing for and attending the CF Summit in Basel."),Object(o.b)("h2",{id:"5th-october-2018"},"5th October 2018"),Object(o.b)("p",null,"The team have been preparing for the CF Summit in Basel next week."),Object(o.b)("p",null,"Highlights for this week (continuing from last week):"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"E2E Tests and Automation - Focusing on making the E2E tests more resilient to timing issues. ")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Metrics - Added Diego Cell to the App Instances table when metrics are available and added a Cell view which shows metrics for a given Diego cell."))),Object(o.b)("p",null,"Fixes:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Ensure we handle orgs with no users ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/3098"}),"#","3098")," - fixes a bug creating a space in a new org.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Endpoint Registration: Only show SSO option for CF Endpoint type ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/3105"}),"#\\3105")))),Object(o.b)("h2",{id:"28th-september-2018"},"28th September 2018"),Object(o.b)("p",null,"This week saw the release of 2.1.1 and an update 2.1.2. It was necessary to tag a 2.1.2 release to resolve a broken backend dependency that would affect users deploying via 'cf push'. You should use 2.1.2 and not 2.1.1. "),Object(o.b)("p",null,Object(o.b)("em",{parentName:"p"},"2.1.2 Highlights")),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Fix go-flags dependency pinned version broken ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/3071"}),"#","3071"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"App wall filtering can stop working with some filter combinations ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/3043"}),"#","3043"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Can not connect a metrics endpoint ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/3035"}),"#","3035"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Backend build issue due to the pinned commit for a dependency being removed ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/3060"}),"#","3060"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Metrics: Wrong job can be matched up when there are multiple jobs ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/3057"}),"#","3057")))),Object(o.b)("p",null,"Highlights for this week (continuing from last week):"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Extensions - Work continues on adding extension points in the UI. Extensions is targeted for 2.2.0 in October.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"E2E Tests and Automation - Focusing on making the E2E tests more resilient to timing issues. ")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Metrics - Work to tidy up the existing Cloud Foundry Application metrics is complete."))),Object(o.b)("h2",{id:"21st-september-2018"},"21st September 2018"),Object(o.b)("p",null,"This week saw the release of 2.1.0 - the highlights are:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Stratos frontend can be pre-built before pushing to Cloud Foundry to enable AOT and reduce push time"),Object(o.b)("li",{parentName:"ul"},"SSO support refinements with the ability to now connect a Cloud Foundry endpoint using SSO in addition to SSO login to Straos itself"),Object(o.b)("li",{parentName:"ul"},"Ability to specify manifest overrides when deploying an application"),Object(o.b)("li",{parentName:"ul"},"Ability to optionally specify Client ID anc Client Secret when registering an endpoint"),Object(o.b)("li",{parentName:"ul"},"Add ability to restage an application"),Object(o.b)("li",{parentName:"ul"},"Endpoints list now shows logged in user's username and whether they're an admin"),Object(o.b)("li",{parentName:"ul"},"Switched to new Stratos logo for login and about pages"),Object(o.b)("li",{parentName:"ul"},"Backend improvements to make it easier for developers to develop with"),Object(o.b)("li",{parentName:"ul"},"Security fixes")),Object(o.b)("p",null,"Full release information is available ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/releases/tag/2.1.0"}),"here"),"."),Object(o.b)("p",null,"Highlights for this week (continuing from last week):"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Extensions - Work continues on adding extension points in the UI. Extensions is targeted for 2.2.0 in October.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"E2E Tests and Automation - Focusing on making the E2E tests more resilient to timing issues. We have also spent time getting the E2E tests to run against BrowserStack to allow us to automate testing of Stratos across multiple browser types/platforms.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Metrics - Work to tidy up the existing Cloud Foundry Application metrics is complete.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"JSON Schema support for Service Instance binding - We have been working to update PR ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2997"}),"#2997")," to get this feature into Stratos."))),Object(o.b)("p",null,"Fixes/Misc:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Fix app wall filtering issue ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3043"}),"#3043")),Object(o.b)("li",{parentName:"ul"},"Fix for Connect button not being enabled when SSO is the default ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3004"}),"#3004")),Object(o.b)("li",{parentName:"ul"},"Version number always reports 'dev' ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3001"}),"#3001")),Object(o.b)("li",{parentName:"ul"},"Diagnostics does not show GitHub details when cloned via HTTPS ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3007"}),"#3007")),Object(o.b)("li",{parentName:"ul"},"Fix for NULL Client Secret bug ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3015"}),"#3015")),Object(o.b)("li",{parentName:"ul"},"Fix bug where token IDs are not set properly when upgrading from a previous version ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/3017"}),"#3017"))),Object(o.b)("h2",{id:"14th-september-2018"},"14th September 2018"),Object(o.b)("p",null,"We've been preparing the 2.1.0 release this week. This will be published next week. Going forward we will be publishing a new release every month. The release notes for 2.1.0 have been created and are ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/blob/master/CHANGELOG.md#210"}),"here"),"."),Object(o.b)("p",null,"Highlights for this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Extensions - Work continues on adding extension points in the UI. We have PRs up to support adding new side-nav items, tabs and actions. This already goes beyond what could be done in V1 of Stratos. The extension mechanism is also much cleaner due to the use of decorators. Extensions is targeted for 2.2.0 in October.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"E2E Tests and Automation - Continuing to build out the E2E test suite and automate the deploy and test of Stratos in different environments (pushed to Cloud Foundry, pushed to Cloud Foundry with MySQL and Postgres, pushed to Cloud Foundry with SSO, Docker compose, Docker All-in-One)")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Metrics - Work is almost complete on improving the metrics integration and presentation in the UI. Rather than display a timeline under each graph, we are switching to a control to allow you to choose the time period."))),Object(o.b)("p",null,"Other updates:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Allow auto-registration name to be configured ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2986"}),"#2986")),Object(o.b)("li",{parentName:"ul"},"SSO: Refinements ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2982"}),"#2982"),Object(o.b)("ul",{parentName:"li"},Object(o.b)("li",{parentName:"ul"},"Fix consistency of SSO casing and hyphenation => 'Single Sign-On'"),Object(o.b)("li",{parentName:"ul"},"Make SSO default when connecting if enabled for the endpoint"),Object(o.b)("li",{parentName:"ul"},"Move the SSO Allowed checkbox to the bottom in 'Advanced Options', so that the form does not move when the checkbox is checked and the advisory text appears"))),Object(o.b)("li",{parentName:"ul"},"Add check to make sure DB Schema migrations have completed (fixes an issue with diagnostics and a possible race-condition when deployed via Helm or Docker Compose) ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2977"}),"#2977"))),Object(o.b)("h2",{id:"7th-september-2018"},"7th September 2018"),Object(o.b)("p",null,"Update for this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Single Sign-On - Added the ability to enable SSO Login when using the Setup screen.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Metrics - Work continues to improve the metrics integration and presentation in the UI")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Extensions - Work has started on adding extension points in the UI. This will be accomplished via decorators, in the same way that Angular uses decorators for Components etc. ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2962"}),"#2962"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Deploy App Manifest overrides - Added an extra step in the 'Deploy App' flow to allow you to override manifest settings before deploying ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2924"}),"#2924")," ")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Show Service plan cost when selecting a service plan (if not free) ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2959"}),"#2959"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"E2E Tests - Resolved GitHub rate limits issues when running E2E Tests ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2949"}),"#2949"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Travis - The Travis build has been restructured to run jobs in parallel and E2E tests now run against PRs in addition to branches."))),Object(o.b)("h2",{id:"31st-august-2018"},"31st August 2018"),Object(o.b)("p",null,"Update for this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Go-backend re-structure - The additional cleanup work has been merged.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Single-Sign-On - Further work on Single-Sign On:"),Object(o.b)("ul",{parentName:"li"},Object(o.b)("li",{parentName:"ul"},"Improvements - improve error handling, add navigate straight to login option ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2522"}),"#2522")),Object(o.b)("li",{parentName:"ul"},"Link tokens rather than copying them ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2916"}),"#2916")),Object(o.b)("li",{parentName:"ul"},"Allow a Cloud Foundry endpoint to be connected with SSO login ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2928"}),"#2928")))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Allow Client ID and Secret to be set when registering an endpoint ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2920"}),"#2920"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Scalability:"),Object(o.b)("ul",{parentName:"li"},Object(o.b)("li",{parentName:"ul"},"Change application list in service instance table row from vertical to chip list ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2915"}),"#2915")),Object(o.b)("li",{parentName:"ul"},"Convert space apps list from local to remote ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2913"}),"#2913")))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Metrics - Work has started on tidying up and improving the metrics views"))),Object(o.b)("h2",{id:"24th-august-2018"},"24th August 2018"),Object(o.b)("p",null,"Update for this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Go-backend re-structure - This work has now been merged and should make it easier to develop with and contribute to. Some additional clean up was done and is awaiting PR review.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Extended end-to-end test suite - Further work to build-out the E2E test suite. See:"),Object(o.b)("ul",{parentName:"li"},Object(o.b)("li",{parentName:"ul"},"Services E2E: Service Instance creation with App Binding ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2855"}),"#2855")),Object(o.b)("li",{parentName:"ul"},"E2E: Basic Application Routes tests ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2862"}),"#2862")),Object(o.b)("li",{parentName:"ul"},"E2E: Basic Application Instances tests ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2863"}),"#2863")),Object(o.b)("li",{parentName:"ul"},"E2E: Basic test for Cf/Org/Space users tables ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2904"}),"#2904")))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Small improvements and fixes for the Diagnostics page ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2860"}),"#2860")))),Object(o.b)("h2",{id:"17th-august-2018"},"17th August 2018"),Object(o.b)("p",null,"Update for this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"2.0.1 - We tagged a 2.0.1 release. This is identical to 2.0.0 and only fixes an issue with a broken dependency - one of the pinned dependencies was no longer working. This issue only affects you if you were pushing to Cloud Foundry from the 2.0.0 tag.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Pre-built UI - We added the ability to pre-build the UI before pushing to Cloud Foundry. This allows you to build the UI with AOT (Ahead-of-time) compilation enabled and push to CF. This will also reduce push time. See the doc ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/tree/master/deploy/cloud-foundry#pre-building-the-ui"}),"Pre-building the UI"),".")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Go-backend re-structure. Work is almost complete on re-structuring the go backend to make it easier to develop with and contribute to. See issue ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/2815"}),"#2815"),".")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Extended end-to-end test suite"))),Object(o.b)("h2",{id:"10th-august-2018"},"10th August 2018"),Object(o.b)("p",null,"A similar update to last week, focusing on metrics, testing and the community."),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Testing the new metrics deployment process."),Object(o.b)("li",{parentName:"ul"},"Improving the end to end test setup process, this will enable better coverage of service tests."),Object(o.b)("li",{parentName:"ul"},"Improving test coverage, both unit and end to end, of the often used list component."),Object(o.b)("li",{parentName:"ul"},"Improving test coverage of entity validation, another often used component."),Object(o.b)("li",{parentName:"ul"},"Manage application stats requests better in the application wall when there are many many started apps."),Object(o.b)("li",{parentName:"ul"},"Investigating, solving and shepherding community issues. Some of the stand out ones..",Object(o.b)("ul",{parentName:"li"},Object(o.b)("li",{parentName:"ul"},"Stratos URLs are now consistent. Previously for the same CF the id would change every time it's registered, meaning bookmarks would need updating following every re-registration. Now as long as the CF API url doesn't change the CF id in the url will remain the same. - ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2798"}),"https://github.com/cloudfoundry/stratos/issues/2798")),Object(o.b)("li",{parentName:"ul"},"Correctly report application instance counts with respect to app state - ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2797"}),"https://github.com/cloudfoundry/stratos/issues/2797")),Object(o.b)("li",{parentName:"ul"},"Apply permissions to application actions (start, restart, etc) - ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2806"}),"https://github.com/cloudfoundry/stratos/issues/2806"))))),Object(o.b)("h2",{id:"3-august-2018"},"3 August 2018"),Object(o.b)("p",null,"This week we've focused on.."),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Making metrics components easier to deploy. This will help us apply polish and publicise CF metrics in the coming weeks."),Object(o.b)("li",{parentName:"ul"},"Improving test suites and coverage."),Object(o.b)("li",{parentName:"ul"},"Responding to community issues. There's been an increase in use and some great contributions."),Object(o.b)("li",{parentName:"ul"},"Fixing older, but still valid, issues that haven't quite been important to address at the time.")),Object(o.b)("p",null,"In addition we\u2019ve created a short (a few minutes) survey to get a better idea how the community plan to use Stratos. Answers and feedback will directly impact the direction we take Stratos, so the quicker we have responses the quicker we can act on them. Follow this link to start answering ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://www.surveymonkey.com/r/2L8XWST"}),"https://www.surveymonkey.com/r/2L8XWST")),Object(o.b)("h2",{id:"27-july-2018"},"27 July 2018"),Object(o.b)("p",null,"The main news this week is that we have released a first version of Stratos 2.0."),Object(o.b)("p",null,"We've been focused over the past weeks on fixing bugs and improving tests and we're delighted to have reached this milestone."),Object(o.b)("p",null,"The release details are available here - ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/releases/tag/2.0.0"}),"https://github.com/cloudfoundry/stratos/releases/tag/2.0.0"),"."),Object(o.b)("p",null,"We've also started to catch up on some of the outstanding PRs, especially submitted from the community, for example:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Change DB schema and backend to support storing a client/secret for each Endpoint ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2622"}),"#","2622")),Object(o.b)("li",{parentName:"ul"},"Fix migrate script to work in Postgresql ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2601"}),"#","2601"))),Object(o.b)("h2",{id:"20-july-2018"},"20 July 2018"),Object(o.b)("p",null,"This week the focus has been on further testing and refinement of Release Candidate 2."),Object(o.b)("p",null,"We will be publishing a Release Candidate 3 on Monday 23 July. We expect this to be the final RC and will most likely promote this to be the final Version 2 release later next week."),Object(o.b)("p",null,"We've been focused on more test automation and building out more end-to-end tests, in addition to fixing a few bugs."),Object(o.b)("p",null,"We had an issue with the Angular AOT + build optimization which pushed the final RC into next week. This took a while to get to the bottom of."),Object(o.b)("p",null,"For a full list of merged PRs this week, see: ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pulls?page=1&q=is%3Apr+is%3Amerged+updated%3A%3E%3D2018-07-13&utf8=%E2%9C%93"}),"Merged PRs"),"."),Object(o.b)("h2",{id:"13-july-2018"},"13 July 2018"),Object(o.b)("p",null,"The SUSE team has been participating in SUSE Hack Week, so there is no change in status this week."),Object(o.b)("p",null,"Work resumes next week on getting a first 2.0 release published."),Object(o.b)("h2",{id:"06-july-2018"},"06 July 2018"),Object(o.b)("p",null,"This week the focus has been on further testing and refinement of Release Candidate 2."),Object(o.b)("p",null,"We've been identifying and fixing issues - see: ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aclosed+updated%3A%3E%3D2018-07-02+"}),"Merged PRs"),"."),Object(o.b)("h2",{id:"29-june-2018"},"29 June 2018"),Object(o.b)("p",null,"This week the focus has been on creating a Release Candidate of Version 2."),Object(o.b)("p",null,"In fact, we published two Release Candidates - at the start and end of the week - full details here:\n",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/releases"}),"https://github.com/cloudfoundry/stratos/releases")),Object(o.b)("p",null,"A large number of bugs and smaller issues have been resolved since last week's Beta 2 release - full details here: ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/compare/2.0.0-beta-002...2.0.0-rc2"}),"https://github.com/cloudfoundry/stratos/compare/2.0.0-beta-002...2.0.0-rc2")),Object(o.b)("p",null,"Work has been focused on testing the Release Candidates and fixing defects."),Object(o.b)("h2",{id:"22-june-2018"},"22 June 2018"),Object(o.b)("p",null,"This week the focus has been on creating a second Beta release of Version 2."),Object(o.b)("p",null,"A large number of bugs and smaller issues have been resolved - full details here: ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/releases/tag/2.0.0-beta-002"}),"https://github.com/cloudfoundry/stratos/releases/tag/2.0.0-beta-002"),"."),Object(o.b)("h2",{id:"15-june-2018"},"15 June 2018"),Object(o.b)("p",null,"We are working towards a release of V2. We are now functionally complete and are working through priority 1 issues and defects."),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"The release schedule is updated here - ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"/docs/roadmap"}),"Roadmap"),"."),Object(o.b)("li",{parentName:"ul"},"Priority 1 defects are labelled P1 - you can view them with this ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3AP1"}),"Filter")),Object(o.b)("li",{parentName:"ul"},"We have tagged a Beta 1 of Version 2 of Stratos today - ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/releases/tag/v2.0.0-beta-001"}),"https://github.com/cloudfoundry/stratos/releases/tag/v2.0.0-beta-001"))),Object(o.b)("p",null,"We've been working through a large number of defects this week -"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Deploy info card shows both file and folder info ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2351"}),"#","2351")),Object(o.b)("li",{parentName:"ul"},"App Service Instances: Modal appears off screen ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2347"}),"#","2347")),Object(o.b)("li",{parentName:"ul"},"Users list is empty after cancel ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2339"}),"#","2339")),Object(o.b)("li",{parentName:"ul"},"We still show large no connected CF endpoints even when you connect a metrics endpoint ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2332"}),"#","2332")),Object(o.b)("li",{parentName:"ul"},"Connected endpoint does not show 'unregister' action ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2321"}),"#","2321")),Object(o.b)("li",{parentName:"ul"},"Service instance page shows no 'no cf connected' warning ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2320"}),"#","2320")),Object(o.b)("li",{parentName:"ul"},"No page header on Cloud Foundry pages when you go directly there ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2319"}),"#","2319")),Object(o.b)("li",{parentName:"ul"},"Service Instance entity is not updated after unbinding an app ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2317"}),"#","2317")),Object(o.b)("li",{parentName:"ul"},"Service broker card intermittently appears immediately below service summary card ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2314"}),"#","2314")),Object(o.b)("li",{parentName:"ul"},"Select cf/org/space in create service instance stepper mentions ",Object(o.b)("inlineCode",{parentName:"li"},"app")," ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2313"}),"#","2313")),Object(o.b)("li",{parentName:"ul"},"Adding a space scoped service should not show org/space selection step ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2311"}),"#","2311")),Object(o.b)("li",{parentName:"ul"},"Front-end unit tests are unreliable in Travis ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2308"}),"#","2308")),Object(o.b)("li",{parentName:"ul"},"Not all backend tests are run ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2300"}),"#","2300")),Object(o.b)("li",{parentName:"ul"},"Log Stream token refresh does not work ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2299"}),"#","2299")),Object(o.b)("li",{parentName:"ul"},"Marketplace: Service Broker card should be hidden if the broker isn't returned by API ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2279"}),"#","2279")),Object(o.b)("li",{parentName:"ul"},"Endpoint Users are not refetched when an endpoint is reconnected as a different user. ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2274"}),"#","2274")),Object(o.b)("li",{parentName:"ul"},"Marketplace service cards tags list fails to expand ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2263"}),"#","2263")),Object(o.b)("li",{parentName:"ul"},"App bound service is shown in services to bind to list ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2253"}),"#","2253")),Object(o.b)("li",{parentName:"ul"},"Error response handling is broken ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2242"}),"#","2242")),Object(o.b)("li",{parentName:"ul"},"Investigate issue with space-scoped services being returned incorrectly by the ",Object(o.b)("inlineCode",{parentName:"li"},"List Services for Space")," request ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2240"}),"#","2240")),Object(o.b)("li",{parentName:"ul"},"App Log Stream shows ",Object(o.b)("inlineCode",{parentName:"li"},"Connecting....")," for apps that aren't running ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2235"}),"#","2235")),Object(o.b)("li",{parentName:"ul"},"Map Existing Routes: Sort by apps attached is broken ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2210"}),"#","2210")),Object(o.b)("li",{parentName:"ul"},"Application: OFFLINE WHILE UPDATING state only allows the delete action. ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2208"}),"#","2208")),Object(o.b)("li",{parentName:"ul"},"Cf/Org/Space filters are not updating on endpoint change ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2162"}),"#","2162")),Object(o.b)("li",{parentName:"ul"},"Component effects are cropped in steppers ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2116"}),"#","2116")),Object(o.b)("li",{parentName:"ul"},"Cloud Foundry orgs and space views contain multiple app-headers ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2051"}),"#","2051")),Object(o.b)("li",{parentName:"ul"},"2nd row of tabs sometimes disappears ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2005"}),"#","2005")),Object(o.b)("li",{parentName:"ul"},"Instances tab shows Unknown when scaling ","(","with crashed app",")"," ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2002"}),"#","2002")),Object(o.b)("li",{parentName:"ul"},"Console setup improvements ","#","2 ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/1974"}),"#","1974")),Object(o.b)("li",{parentName:"ul"},"Services page does not update after connecting/disconnected an SCF ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/1973"}),"#","1973")),Object(o.b)("li",{parentName:"ul"},"White bar flashes at top of page on Cloud Foundry page ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/1963"}),"#","1963")),Object(o.b)("li",{parentName:"ul"},"Show service type in service wall card ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2315"}),"#","2315")),Object(o.b)("li",{parentName:"ul"},"Show space name in space broker card ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2312"}),"#","2312")),Object(o.b)("li",{parentName:"ul"},"Add confirmation modals where required ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2257"}),"#","2257")),Object(o.b)("li",{parentName:"ul"},"Add git commit id and whether user is an admin on the about page ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2246"}),"#","2246")),Object(o.b)("li",{parentName:"ul"},"Update base images for git vulnerability CVE 2018-11235 ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2241"}),"#","2241")),Object(o.b)("li",{parentName:"ul"},"Update service steppers following async stepper changes ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2234"}),"#","2234")),Object(o.b)("li",{parentName:"ul"},"CF Permissions - Apply to user management ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2226"}),"#","2226")),Object(o.b)("li",{parentName:"ul"},"CF Permissions - Apply to services ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2225"}),"#","2225")),Object(o.b)("li",{parentName:"ul"},"CF Permissions - Apply to App Wall + Summary ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/issues/2224"}),"#","2224")),Object(o.b)("li",{parentName:"ul"},"V1 e2e fix ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/pull/2316"}),"#","2316")," (",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/nwmac"}),"nwmac"),")")),Object(o.b)("h2",{id:"08-june-2018"},"08 June 2018"),Object(o.b)("p",null,"The team have been working on the following issues and PRs this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Front-end unit tests are unreliable in Travis ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/2308"}),"#3208")," - we're seeing a lot of problems with the front-end unit tests when running in Travis - we're continuing to dig into this issue to understand what the cause is, since this is affecting reliability of PR gate checks.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Services permissions ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2284"}),"#2284")," - wiring the user permissions service into the Service UI to ensure users are only presented with actions that they are permitted to perform.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Allow metrics endpoint token to be shared ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2283"}),"#2283")," - adding support for the admin user to connect to a Prometheus metrics endpoint and then make that connection available to all users. Note that non-admins can only see metrics for applications that they have permission to view.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Show whether user is an admin on the about page ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2306"}),"#2306")," - we now indicate on the about page if the current user is an administrator of Stratos.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Add Permissions to CF Users tables ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2291"}),"#2291")," - wired in the user permissions service into the Cloud Foundry user management UI.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Wire in actions to app state ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2288"}),"#2288")," - actions on the application view now use the same rules as in V1 to determine which actions should be shown based on the current application state.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Quicker e2e tests for PRs ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2273"}),"#2273")," - changed the way e2e tests run for PRs. They will now use a quicker local deployment rather than a full deployment in docker.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Only show add and deploy buttons when there is at least 1 connected CF ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2285"}),"#2285")," - we now only show the add and deploy buttons on the application wall when there is a Cloud Foundry available.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Fetch cf users when not cf admin ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2282"}),"#2282")," - ensuring that we use different APIs call when the user is not an admin in order to retrieve the data to display for the user list.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Hide service broker card if broker information isn't available ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2287"}),"#2287")," - we now hide the service broker card if we can not retrieve the broker metadata.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Only allow password change if user has password.write scope ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2278"}),"#2278")," - user is now only presented with the option to change their password if they have permission to do so.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Backend logging improvements ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2267"}),"#2267")," - first round of tidy up to the back-end logging, including not logging an error when verifying the user's seesion when they don't have a valid session.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Use local fonts ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2260"}),"#2260")," - all fonts are now served up by the app itself to allow air-gapped deployment.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Endpoint confirmation modals ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2258"}),"#2258")," - added confirmation modals when disconnecting or un-registering and endpoint.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Added theming section to developer guide readme ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2249"}),"#2249")," - added documentation on how theming is done for Stratos.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Update permissions when when entities are updated ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2221"}),"#2221")," - we now ensure that permissions are updated when endpoints (and other entities) are updated in Stratos."))),Object(o.b)("h2",{id:"01-june-2018"},"01 June 2018"),Object(o.b)("p",null,"The team have been working on the following issues and PRs this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Upgrade to Angular 6 ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2227"}),"#2227")," - Completed work and testing. Will merge early next week.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Edit service instance from Services Wall ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2233"}),"#2233")," - Added ability to edit an existing service instance.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"E2E Tests ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/1523"}),"#1523")," - Continuing to extend E2E test suite.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Fix compression issue ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2248"}),"#2248")," - Fixed an issue when Stratos accessed a Cloud Foundry instance with gzip compression enabled. Thanks to everyone for their help with this one.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Fix App SSH (Broken when auth and token endpoints are different) ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2250"}),"#2250")," - Fixed an issue with Application SSH for some CF deplyoments.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Fix application issue on reload when served by backend ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2238"}),"#2238")," - Fixed an issue where refreshing the browser on application pages resulted in a 404 (when deployed via cf push)"))),Object(o.b)("h2",{id:"25-may-2018"},"25 May 2018"),Object(o.b)("p",null,"The team have been working on the following issues and PRs this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Upgrade to Angular 6 ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2227"}),"#2227"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Handle async request progress/success/failure in modals ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2223"}),"#2223")," - Improving busy state and error feedback in modals - e.g. when creating an application, creating a space etc")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Service Summary tab ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2219"}),"#2219")," - add a summary tab to the view for a service, to show summary metadata")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Add support for back-end custom plugins ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2217"}),"#2217"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Apply user permissions to CF pages (2) ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2212"}),"#2212")," - Completion of work to wire in user permissions into the Cloud Foundry view"))),Object(o.b)("h2",{id:"18-may-2018"},"18 May 2018"),Object(o.b)("p",null,"The team have been working on the following issues and PRs this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"User permissions ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2147"}),"#2147")," - adding in the framework to control UI elements based on the user's permissions")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Apply user permissions to CF pages ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2198"}),"#2198")," - appropriately show the CF actions a user can perform based on their permissions")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Service instances view ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/2074"}),"#2074")," - adding a view to show service instances")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Services Wall: Create Services instance ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2163"}),"#2163")," - adding support for creating service instances from the service marketplace view")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"App Services tab: Allow user to bind a service instance ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2188"}),"#2188"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"E2E Tests and E2E Test setup improvements ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2183"}),"#2183"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Add support for Angular XSRF protection ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2153"}),"#2153")," - adding support for the Angular XSRF protection mechanism")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Remove deprecated API & Add confirmation dialogs when detaching/removing service bindings ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2193"}),"#2193")))),Object(o.b)("h2",{id:"11-may-2018"},"11 May 2018"),Object(o.b)("p",null,"The work to get V2 to the same level of functionality as V1 is going well and we're nearing completion - the team have been working on the following issues and PRs this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Add restart app button ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2140"}),"#2140")," - adding restart action to applications")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"CF Push: Bump up memory further ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2135"}),"#2135")," - increase memory when pushing to work around the memory-hungry Angular compiler")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Service instances view ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/2074"}),"#2074")," - adding a view to show service instances")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"User permissions ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2147"}),"#2147")," - adding in the framework to control UI elements based on the user's permissions")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Customizations ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2133"}),"#2133")," - initial support for customizing Stratos (theme etc)")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"E2E Tests ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/1523"}),"#1523")," - putting in place the E2E framework for V2, getting this working in Travis and porting over the V1 Endpoints tests.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Delete App should show dependencies and allow optional deletion ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2044"}),"#2044")," - when deleting an application the user is shown the application dependencies (routes, service instances) and is able to delete these with the application or leave them in place for use by other applications")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Cloud Foundry: Manage Users ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/1541"}),"#1541")," - re-introducing the equivalent features that V1 has allowing user to manage user roles across Cloud Foundry"))),Object(o.b)("h2",{id:"4-may-2018"},"4 May 2018"),Object(o.b)("p",null,"The team have been working on the following issues and PRs this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"E2E Tests ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/1523"}),"#1523")," - putting in place the E2E framework for V2, getting this working in Travis and porting over the V1 Endpoints tests.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Delete App should show dependencies and allow optional deletion ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2044"}),"#2044")," - when deleting an application the user is shown the application dependencies (routes, service instances) and is able to delete these with the application or leave them in place for use by other applications")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Cloud Foundry: Manage Users ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/1541"}),"#1541")," - re-introducing the equivalent features that V1 has allowing user to manage user roles across Cloud Foundry")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Implement Create Service Instance ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/2043"}),"#2043")," - adding support for creating service instances")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Service Instance creation: Support space-scoped broker provided plans ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2111"}),"#2111"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Make Service Instance creation wizard service plan visibility aware ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2109"}),"#2109"))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Return better error information from API passthroughs ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2085"}),"#2084")))),Object(o.b)("h2",{id:"27-april-2018"},"27 April 2018"),Object(o.b)("p",null,"The team have been working on the following issues this week:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"GitHub tab/deploy updates ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/2067"}),"#2067")," - When deploying an application from GitHub, we now allow the user to select a commit from their selected branch. When viewing the GitHub tab of an application, the user can see the list of commits and update the application from a different commit on the branch.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Deploy App: Add support for an archive file or local folder ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/2040"}),"#2040")," - In addition to Git deployment, users can now browse to a local application archive file or folder and deploy using that.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"User Profile: Implement edit and password change as per V1 ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/2040"}),"#2062")," - Users can now edit their profile metadata and change their password.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Create & List Service Instances - ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2086"}),"#2086")," - adding the ability to view and create Service Instances.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Delete App should show dependencies and allow optional deletion ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/pull/2044"}),"#2044")," - when deleting and application the user is shown the application dependencies(routes, service instances) and is able to delete these with the application or leave them in place for use by other applications")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Cloud Foundry: Manage Users ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/cloudfoundry/stratos/issues/1541"}),"#1541")," - re-introducing the equivalent features that V1 has allowing user to manage user roles across Cloud Foundry"))))}c.isMDXComponent=!0},149:function(e,t,a){"use strict";a.d(t,"a",(function(){return u})),a.d(t,"b",(function(){return h}));var n=a(0),r=a.n(n);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function s(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?i(Object(a),!0).forEach((function(t){o(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):i(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function l(e,t){if(null==e)return{};var a,n,r=function(e,t){if(null==e)return{};var a,n,r={},o=Object.keys(e);for(n=0;n<o.length;n++)a=o[n],t.indexOf(a)>=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)a=o[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var b=r.a.createContext({}),c=function(e){var t=r.a.useContext(b),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},u=function(e){var t=c(e.components);return r.a.createElement(b.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},d=r.a.forwardRef((function(e,t){var a=e.components,n=e.mdxType,o=e.originalType,i=e.parentName,b=l(e,["components","mdxType","originalType","parentName"]),u=c(a),d=n,h=u["".concat(i,".").concat(d)]||u[d]||p[d]||o;return a?r.a.createElement(h,s(s({ref:t},b),{},{components:a})):r.a.createElement(h,s({ref:t},b))}));function h(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=a.length,i=new Array(o);i[0]=d;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:n,i[1]=s;for(var b=2;b<o;b++)i[b]=a[b];return r.a.createElement.apply(null,i)}return r.a.createElement.apply(null,a)}d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/website/site-dist/fbb73fc3.5e9c12be.js b/website/site-dist/fbb73fc3.5e9c12be.js new file mode 100644 index 0000000000..cd9e21f480 --- /dev/null +++ b/website/site-dist/fbb73fc3.5e9c12be.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{143:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return a})),n.d(t,"metadata",(function(){return o})),n.d(t,"rightToc",(function(){return c})),n.d(t,"default",(function(){return u}));var i=n(2),l=n(6),r=(n(0),n(149)),a={},o={id:"planning/angular",isDocsHomePage:!1,title:"angular",description:"Technology Refresh",source:"@site/docs/planning/angular.md",permalink:"/docs/planning/angular",editUrl:"https://github.com/cloudfoundry/stratos/edit/master/website/docs/planning/angular.md"},c=[{value:"Migrate Angular from AngularJS",id:"migrate-angular-from-angularjs",children:[]},{value:"Migrate to Material Design",id:"migrate-to-material-design",children:[{value:"Milestone 1: CF Applications -> Endpoint mgmt and Application views (Complete in Sprint 22)",id:"milestone-1-cf-applications---endpoint-mgmt-and-application-views-complete-in-sprint-22",children:[]},{value:"Milestone 1b (Complete in Sprint 22)",id:"milestone-1b-complete-in-sprint-22",children:[]},{value:"Milestone 2 (Complete in Sprint 24)",id:"milestone-2-complete-in-sprint-24",children:[]},{value:"Milestone 3 (Complete in Sprint 26)",id:"milestone-3-complete-in-sprint-26",children:[]},{value:"Milestone 4: Misc (Complete in Sprint 28)",id:"milestone-4-misc-complete-in-sprint-28",children:[]},{value:"Milestone 5 (Complete in Sprint 30)",id:"milestone-5-complete-in-sprint-30",children:[]},{value:"To be scheduled into Milestones:",id:"to-be-scheduled-into-milestones",children:[]}]}],p={rightToc:c};function u(e){var t=e.components,n=Object(l.a)(e,["components"]);return Object(r.b)("wrapper",Object(i.a)({},p,n,{components:t,mdxType:"MDXLayout"}),Object(r.b)("h1",{id:"technology-refresh"},"Technology Refresh"),Object(r.b)("p",null,"The focus for the first part of 2018 is to complete the move from AngularJS to Angular. This is a significant amount of work."),Object(r.b)("h2",{id:"migrate-angular-from-angularjs"},"Migrate Angular from AngularJS"),Object(r.b)("p",null,"Move to a newer framework that is being actively developed and will carry us forward for longer. This will make future migrations much easier (Angular 2 => 4 => 5 => 6)"),Object(r.b)("p",null,"Note:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Back-end stays the same (folder structure will most likely be moved around)"),Object(r.b)("li",{parentName:"ul"},"Deployment and other scripts, artefacts remain the same (tweaks as necessary to build the V2 code)")),Object(r.b)("p",null,"Stack:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Angular 5"),Object(r.b)("li",{parentName:"ul"},"Typescript"),Object(r.b)("li",{parentName:"ul"},"RxJS"),Object(r.b)("li",{parentName:"ul"},"Angular Material")),Object(r.b)("h2",{id:"migrate-to-material-design"},"Migrate to Material Design"),Object(r.b)("p",null,"Adopt material design while keeping essence of the current Angular 1 app:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Use Material Design as the visual language for the UX",Object(r.b)("ul",{parentName:"li"},Object(r.b)("li",{parentName:"ul"},"Rich language"),Object(r.b)("li",{parentName:"ul"},"Used by a growing number of projects, not just those from Google"))),Object(r.b)("li",{parentName:"ul"},"Adopt Material Design approach, patterns and components"),Object(r.b)("li",{parentName:"ul"},"Leverage angular-material library for UI components"),Object(r.b)("li",{parentName:"ul"},"Only create custom components when needed"),Object(r.b)("li",{parentName:"ul"},"Adopt angular-material approach to theming"),Object(r.b)("li",{parentName:"ul"},"Improve layout and use more visual cues to help locate date and issues")),Object(r.b)("h1",{id:"migration-milestones"},"Migration Milestones"),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"This material is out of date. We will update once schedule planning is complete.")),Object(r.b)("h3",{id:"milestone-1-cf-applications---endpoint-mgmt-and-application-views-complete-in-sprint-22"},"Milestone 1: CF Applications -> Endpoint mgmt and Application views (Complete in Sprint 22)"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"App Wall"),Object(r.b)("li",{parentName:"ul"},"App View",Object(r.b)("ul",{parentName:"li"},Object(r.b)("li",{parentName:"ul"},"Edit"),Object(r.b)("li",{parentName:"ul"},"Routes"),Object(r.b)("li",{parentName:"ul"},"Instances"),Object(r.b)("li",{parentName:"ul"},"SSH"))),Object(r.b)("li",{parentName:"ul"},"Endpoints")),Object(r.b)("h3",{id:"milestone-1b-complete-in-sprint-22"},"Milestone 1b (Complete in Sprint 22)"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Deployment of an Application as per V1.")),Object(r.b)("h3",{id:"milestone-2-complete-in-sprint-24"},"Milestone 2 (Complete in Sprint 24)"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},'Cloud Foundry View (excluding "assign users")')),Object(r.b)("h3",{id:"milestone-3-complete-in-sprint-26"},"Milestone 3 (Complete in Sprint 26)"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Services view",Object(r.b)("ul",{parentName:"li"},Object(r.b)("li",{parentName:"ul"},"Services as a top-level concept"),Object(r.b)("li",{parentName:"ul"},"Improve support for services: Service Keys etc")))),Object(r.b)("h3",{id:"milestone-4-misc-complete-in-sprint-28"},"Milestone 4: Misc (Complete in Sprint 28)"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Add dashboard"),Object(r.b)("li",{parentName:"ul"},"About page"),Object(r.b)("li",{parentName:"ul"},"User profile viewing and edit")),Object(r.b)("h3",{id:"milestone-5-complete-in-sprint-30"},"Milestone 5 (Complete in Sprint 30)"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},'Equivalent functionality of "Assign Users"')),Object(r.b)("h3",{id:"to-be-scheduled-into-milestones"},"To be scheduled into Milestones:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"e2e tests"),Object(r.b)("li",{parentName:"ul"},"unit tests"),Object(r.b)("li",{parentName:"ul"},"error handling"),Object(r.b)("li",{parentName:"ul"},"Support for plugins/extensions"),Object(r.b)("li",{parentName:"ul"},"Support for vendor modifications"),Object(r.b)("li",{parentName:"ul"},"Internationalisation (i18n)"),Object(r.b)("li",{parentName:"ul"},"Theming/Branding"),Object(r.b)("li",{parentName:"ul"},"Deployment support",Object(r.b)("ul",{parentName:"li"},Object(r.b)("li",{parentName:"ul"},"cf push"),Object(r.b)("li",{parentName:"ul"},"helm"),Object(r.b)("li",{parentName:"ul"},"bosh")))))}u.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return s})),n.d(t,"b",(function(){return d}));var i=n(0),l=n.n(i);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function c(e,t){if(null==e)return{};var n,i,l=function(e,t){if(null==e)return{};var n,i,l={},r=Object.keys(e);for(i=0;i<r.length;i++)n=r[i],t.indexOf(n)>=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i<r.length;i++)n=r[i],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var p=l.a.createContext({}),u=function(e){var t=l.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},s=function(e){var t=u(e.components);return l.a.createElement(p.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return l.a.createElement(l.a.Fragment,{},t)}},m=l.a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,a=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),s=u(n),m=i,d=s["".concat(a,".").concat(m)]||s[m]||b[m]||r;return n?l.a.createElement(d,o(o({ref:t},p),{},{components:n})):l.a.createElement(d,o({ref:t},p))}));function d(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,a=new Array(r);a[0]=m;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:i,a[1]=o;for(var p=2;p<r;p++)a[p]=n[p];return l.a.createElement.apply(null,a)}return l.a.createElement.apply(null,n)}m.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/website/site-dist/fcf0d1a0.d19d5e56.js b/website/site-dist/fcf0d1a0.d19d5e56.js new file mode 100644 index 0000000000..120549ebce --- /dev/null +++ b/website/site-dist/fcf0d1a0.d19d5e56.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[43],{144:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return r})),n.d(t,"metadata",(function(){return l})),n.d(t,"rightToc",(function(){return s})),n.d(t,"default",(function(){return b}));var a=n(2),i=n(6),o=(n(0),n(149)),r={id:"customizing",title:"Customizing Stratos",sidebar_label:"Customizing Stratos"},l={id:"guides/customization/customizing",isDocsHomePage:!1,title:"Customizing Stratos",description:"Stratos provides a mechanism for customization - the following customizations are currently supported:",source:"@site/docs/guides/customization/customizing.md",permalink:"/docs/guides/customization/customizing",editUrl:"https://github.com/cloudfoundry/stratos/edit/master/website/docs/guides/customization/customizing.md",sidebar_label:"Customizing Stratos",sidebar:"docs",previous:{title:"Extending Stratos",permalink:"/docs/extensions/introduction"},next:{title:"Theming Stratos",permalink:"/docs/extensions/theming"}},s=[{value:"Approach",id:"approach",children:[{value:"Customizing Images",id:"customizing-images",children:[]},{value:"Customizing the Theme",id:"customizing-the-theme",children:[]},{value:"Changing Styles",id:"changing-styles",children:[]},{value:"Adding new Features",id:"adding-new-features",children:[]},{value:"Changing the Initial Loading Indicator",id:"changing-the-initial-loading-indicator",children:[]}]}],c={rightToc:s};function b(e){var t=e.components,n=Object(i.a)(e,["components"]);return Object(o.b)("wrapper",Object(a.a)({},c,n,{components:t,mdxType:"MDXLayout"}),Object(o.b)("p",null,"Stratos provides a mechanism for customization - the following customizations are currently supported:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Changing the theme colors"),Object(o.b)("li",{parentName:"ul"},"Changing certain image assets (favorite icon, login background and logo)"),Object(o.b)("li",{parentName:"ul"},"Overriding styles"),Object(o.b)("li",{parentName:"ul"},"Adding new functionality"),Object(o.b)("li",{parentName:"ul"},"Changing the initial loading indicator")),Object(o.b)("h1",{id:"migrating-to-stratos-v4-customization"},"Migrating to Stratos V4 Customization"),Object(o.b)("p",null,"In V4 there are breaking customization changes. These changes allow a much improved approach to extensions by opening the door to npm style plugins.\nTo aid in migrating we've provided these instructions."),Object(o.b)("p",null,"1) Before updating to the latest code...\n1) Run ",Object(o.b)("inlineCode",{parentName:"p"},"npm run customize-reset")," to remove all previously created sym links.\n2) Read through the customization documentation below to get a better understanding of the new process.\n1) Update your codebase with the desired v4 code.\n1) Run ",Object(o.b)("inlineCode",{parentName:"p"},"npm install")," (only required first time, this will ensure you have the required version of Angular).\n1) Change directory to ",Object(o.b)("inlineCode",{parentName:"p"},"./build/tools/v4-migration")," and run the migration script ",Object(o.b)("inlineCode",{parentName:"p"},"./migrate.sh"),"."),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"- This will copy your customizations from `custom-src` to a new Angular package `src/frontend/packages/custom_extensions`.\n")),Object(o.b)("p",null,"1) Check that the new package exports your custom module and if applicable your custom-routing module."),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"- The migrate script should do this in `src/frontend/packages/custom_extensions/src/public-api.ts`.\n")),Object(o.b)("p",null,"1) Check that your ts config file defines the public api file."),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),'- `src/tsconfig.json` file\'s `compilerOptions/paths` section should contain something like `"@custom/extensions": ["frontend/packages/custom_extensions/src/public-api.ts"]`.\n')),Object(o.b)("p",null,"1) Check that your new package's package.json defines your custom module and if application custom-routing module."),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"- See `src/frontend/packages/suse_extensions/package.json` file's `stratos` section.\n- Note your `routingModule` entry label should not have a preceding `_`.\n")),Object(o.b)("p",null,"1) Build Stratos in your usual way, for instance ",Object(o.b)("inlineCode",{parentName:"p"},"npm run build"),"."),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"- It could be that this fails due to TypeScript import issues, if so go through these and fix.\n- During build time the custom packages will be discovered and output, see section starting `Building with these extensions`. These should contain the modules your require.\n")),Object(o.b)("p",null,"1) Run Stratos your usual way. Ensure you can navigate to all your custom parts.\n1) Once you are happy everything works as intended remove the old ",Object(o.b)("inlineCode",{parentName:"p"},"./custom-src")," directory and commit you changes."),Object(o.b)("h2",{id:"approach"},"Approach"),Object(o.b)("p",null,"In order to customize Stratos, you will need to fork the Stratos GitHub repository and apply customizations in your fork. Our aim is to minimize any merge conflicts that might occur when re-basing your fork with the upstream Stratos repository."),Object(o.b)("p",null,"Customizations are placed in angular packages in the folder named ",Object(o.b)("inlineCode",{parentName:"p"},"src/frontend/packages"),". In the future you will be able to host these packages in npm and bring them into Stratos in the usual npm dependency way."),Object(o.b)("p",null,"Each package should contain custom Stratos configuration in it's package.json pointing to the modules it will be required to import. "),Object(o.b)("p",null,"stratos.yaml\ncustom theme\ncustom styles\ncustom assets"),Object(o.b)("p",null,"The Stratos approach to customization uses symbolic links. We maintain a default set of resources in the folder ",Object(o.b)("inlineCode",{parentName:"p"},"src/misc/custom"),". When you run ",Object(o.b)("inlineCode",{parentName:"p"},"npm install")," or when you explicitly run ",Object(o.b)("inlineCode",{parentName:"p"},"npm run customize"),", a gulp task (in the file ",Object(o.b)("inlineCode",{parentName:"p"},"build/fe-build.js"),") runs and creates symbolic links, linking the required files to their expected locations withing the ",Object(o.b)("inlineCode",{parentName:"p"},"src")," folder."),Object(o.b)("p",null,"If a required file exists in the ",Object(o.b)("inlineCode",{parentName:"p"},"custom-src")," folder location, the build script will link this file, otherwise, it will link the default resource from ",Object(o.b)("inlineCode",{parentName:"p"},"src/misc/custom"),"."),Object(o.b)("p",null,"Normally, you do not need to run any scripts to apply customizations - they will be applied as part of a ",Object(o.b)("inlineCode",{parentName:"p"},"postinstall")," script that runs automatically when you do an ",Object(o.b)("inlineCode",{parentName:"p"},"npm install"),". You can manually run the following scripts if you update or change the customizations:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},Object(o.b)("inlineCode",{parentName:"p"},"npm run customize")," - creates symbolic links for the required files, looking at the provided customizations and then falling back to default files")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},Object(o.b)("inlineCode",{parentName:"p"},"npm run customize-default")," - creates symbolic links for the required files, ignoring any provided customizations and using the default files")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},Object(o.b)("inlineCode",{parentName:"p"},"npm run customize-reset")," - remove all symbolic links. If you build after running this command you will see errors, as required files are not present."))),Object(o.b)("h3",{id:"customizing-images"},"Customizing Images"),Object(o.b)("p",null,"The following image resources can be changed by creating the specified file in the folder shown:"),Object(o.b)("table",null,Object(o.b)("thead",{parentName:"table"},Object(o.b)("tr",{parentName:"thead"},Object(o.b)("th",Object(a.a)({parentName:"tr"},{align:null}),"File name"),Object(o.b)("th",Object(a.a)({parentName:"tr"},{align:null}),"Folder"),Object(o.b)("th",Object(a.a)({parentName:"tr"},{align:null}),"Description"))),Object(o.b)("tbody",{parentName:"table"},Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"favicon.ico"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"custom-src/frontend"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Favorite icon to use")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"logo.png"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"custom-src/frontend/assets"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Logo to use on login screen and about page")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"nav-logo.png"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"custom-src/frontend/assets"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Logo to use in the top-left side navigation for the application logo")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"login-bg.jpg"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"custom-src/frontend/assets"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Image to use for the login page background")))),Object(o.b)("blockquote",null,Object(o.b)("p",{parentName:"blockquote"},"NOTE: The ",Object(o.b)("inlineCode",{parentName:"p"},"nav-logo.png")," logo should have a height of 36px and a maximum width of 180 pixels.")),Object(o.b)("h3",{id:"customizing-the-theme"},"Customizing the Theme"),Object(o.b)("p",null,"Stratos uses Material Design and the ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"https://material.angular.io/"}),"angular-material")," library. It uses the same approach to theming."),Object(o.b)("p",null,"To create your own theme, create the file ",Object(o.b)("inlineCode",{parentName:"p"},"custom.scss")," in the folder ",Object(o.b)("inlineCode",{parentName:"p"},"custom-src/frontend/sass"),"."),Object(o.b)("p",null,"In this file you can set any or all of the following variables:"),Object(o.b)("table",null,Object(o.b)("thead",{parentName:"table"},Object(o.b)("tr",{parentName:"thead"},Object(o.b)("th",Object(a.a)({parentName:"tr"},{align:null}),"Variable"),Object(o.b)("th",Object(a.a)({parentName:"tr"},{align:null}),"Purpose"))),Object(o.b)("tbody",{parentName:"table"},Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"$stratos-theme"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"The main theme to use for Stratos")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"$stratos-nav-theme"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Theme to use for the side navigation panel")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"$stratos-status-theme"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Theme to use for displaying status in Stratos")))),Object(o.b)("p",null,"Note that you do not have to specify all of these - defaults will be used if they are not set."),Object(o.b)("p",null,"In most cases you will probably want to generate a palette for the primary color for your version of Stratos - an example ",Object(o.b)("inlineCode",{parentName:"p"},"custom.scss")," this for this is shown below:"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"$suse-green: ( 50: #E0F7F0, 100: #B3ECD9, 200: #80E0C0, 300: #4DD3A7, 400: #26C994, 500: #00C081, 600: #00BA79, 700: #00B26E, 800: #00AA64, 900: #009C51, A100: #C7FFE0, A200: #94FFC4, A400: #61FFA8, A700: #47FF9A, contrast: (50: #000000, 100: #000000, 200: #000000, 300: #000000, 400: #ffffff, 500: #ffffff, 600: #ffffff, 700: #ffffff, 800: #ffffff, 900: #ffffff, A100: #000000, A200: #000000, A400: #000000, A700: #000000 ));\n\n$suse-red: ( 50: #ffebee, 100: #ffcdd2, 200: #ef9a9a, 300: #e57373, 400: #ef5350, 500: #f44336, 600: #e53935, 700: #d32f2f, 800: #c62828, 900: #b71c1c, A100: #ff8a80, A200: #ff5252, A400: #ff1744, A700: #d50000, contrast: ( 50: $black-87-opacity, 100: $black-87-opacity, 200: $black-87-opacity, 300: $black-87-opacity, 400: $black-87-opacity, 500: white, 600: white, 700: white, 800: $white-87-opacity, 900: $white-87-opacity, A100: $black-87-opacity, A200: white, A400: white, A700: white, ));\n\n// Create palettes\n$suse-app-primary: mat-palette($suse-green);\n$suse-theme-warn: mat-palette($suse-red);\n\n// Create a theme from the palette (secondary theme is the same as the primary in this example)\n$suse-app-theme: mat-light-theme($suse-app-primary, $suse-app-primary, $suse-theme-warn);\n\n// Set this theme as the one to use\n$stratos-theme: $suse-app-theme;\n")),Object(o.b)("h4",{id:"creating-or-disabling-the-dark-theme"},"Creating or disabling the Dark theme"),Object(o.b)("p",null,"You can also change the Dark theme, if you wish, by defining the following variables:"),Object(o.b)("table",null,Object(o.b)("thead",{parentName:"table"},Object(o.b)("tr",{parentName:"thead"},Object(o.b)("th",Object(a.a)({parentName:"tr"},{align:null}),"Variable"),Object(o.b)("th",Object(a.a)({parentName:"tr"},{align:null}),"Purpose"))),Object(o.b)("tbody",{parentName:"table"},Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"$stratos-dark-theme"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"The dark theme to use for Stratos")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"$stratos-dark-nav-theme"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Dark theme to use for the side navigation panel")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"$stratos-dark-status-theme"),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Dark theme to use for displaying status in Stratos")))),Object(o.b)("p",null,"Note that minimally you must supply ",Object(o.b)("inlineCode",{parentName:"p"},"stratos-dark-theme")," to create a dark theme."),Object(o.b)("p",null,"By default a dark theme is assumed to be available and the default will be used if not overridden. You can disable dark theme support in the UI by setting the following variable in your ",Object(o.b)("inlineCode",{parentName:"p"},"custom.scss"),":"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),"$stratos-dark-theme-supported: false;\n")),Object(o.b)("h3",{id:"changing-styles"},"Changing Styles"),Object(o.b)("p",null,"We don't generally recommend modifying styles, since from version to version of Stratos, we may change the styles used slightly which can mean any modifications you made will need updating. Should you wish to do so, you can modify these in the same ",Object(o.b)("inlineCode",{parentName:"p"},"custom.scss")," file that is used for theming."),Object(o.b)("p",null,"As an example, to disable the login background image, add the following to ",Object(o.b)("inlineCode",{parentName:"p"},"custom.scss"),":"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),".stratos .intro {\n background-image: none;\n}\n")),Object(o.b)("p",null,"Note that the class ",Object(o.b)("inlineCode",{parentName:"p"},"stratos")," has been placed on the ",Object(o.b)("inlineCode",{parentName:"p"},"BODY")," tag of the Stratos application to assist with css selector specificity."),Object(o.b)("h3",{id:"adding-new-features"},"Adding new Features"),Object(o.b)("p",null,"Code for new features should be placed within the ",Object(o.b)("inlineCode",{parentName:"p"},"custom-src/frontend/app/custom")," folder. You can create any sub-folder structure within this folder."),Object(o.b)("p",null,"When you perform an ",Object(o.b)("inlineCode",{parentName:"p"},"npm install")," or explicitly run ",Object(o.b)("inlineCode",{parentName:"p"},"npm run customize"),", the customize script is run and will symlink the folder ",Object(o.b)("inlineCode",{parentName:"p"},"custom-src/frontend/app/custom")," to ",Object(o.b)("inlineCode",{parentName:"p"},"src/frontend/app/custom"),". It will also create a module to import your custom code - this is placed in the file ",Object(o.b)("inlineCode",{parentName:"p"},"src/frontend/app/custom/custom-import.module.ts"),". You should ",Object(o.b)("em",{parentName:"p"},"not")," edit this file."),Object(o.b)("p",null,"Within the ",Object(o.b)("inlineCode",{parentName:"p"},"custom-src/frontend/app/custom")," folder you must create a module in the file ",Object(o.b)("inlineCode",{parentName:"p"},"custom.module.ts")," named ",Object(o.b)("inlineCode",{parentName:"p"},"CustomModule")," - this will be imported into the Stratos application and is the mechanism by which you can add custom code to the front-end."),Object(o.b)("p",null,"We currently expose the following extension points in the Stratos UI:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Changing the component to use for the login screen"),Object(o.b)("li",{parentName:"ul"},"Adding new items to the side navigation menu"),Object(o.b)("li",{parentName:"ul"},"Adding new tabs to the Application, Cloud Foundry, Organization and Space views"),Object(o.b)("li",{parentName:"ul"},"Adding new action buttons to the Application Wall, Application, Cloud Foundry, Organization and Space and Endpoint views")),Object(o.b)("p",null,"We use Decorators to annotate components to indicate that they are Stratos extensions."),Object(o.b)("p",null,"See ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"../extensions/frontend-extensions"}),"Extensions")," for more detail and examples of front-end extensions."),Object(o.b)("h3",{id:"changing-the-initial-loading-indicator"},"Changing the Initial Loading Indicator"),Object(o.b)("p",null,"On slower connections, it can take a few seconds to load the main Javascript resources for Stratos."),Object(o.b)("p",null,"In order to give the user some initial feedback that Stratos is loading, a loading indicator is included in the ",Object(o.b)("inlineCode",{parentName:"p"},"index.html")," file. This gets shown as early as possible, as soon as this main html file has loaded. Once the main code has been fetched, the view refreshes to show the application."),Object(o.b)("p",null,"A default loading indicator is provided that can be changed. To do so, create the following two files:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"custom-src/frontend/loading.css")," - CSS styles to be included in a style block in the head of the index page"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"custom-src/frontend/loading.html")," - HTML markup to be included the the index page to render the loading indicator")),Object(o.b)("p",null,"The files for the default indicator can be found in the ",Object(o.b)("inlineCode",{parentName:"p"},"src/frontend/packages/core/misc/custom")," folder."),Object(o.b)("p",null,"An example of a different loading indicator is included with the ACME sample in ",Object(o.b)("inlineCode",{parentName:"p"},"examples/custom-src/frontend"),"."),Object(o.b)("p",null,"The customization task will insert the appropriate CSS and HTML files into the main index.html file when it runs."),Object(o.b)("p",null,"Take a look at the template for the ",Object(o.b)("inlineCode",{parentName:"p"},"index.html")," file in ",Object(o.b)("inlineCode",{parentName:"p"},"src/frontend/packages/core/misc/custom/index.html"),". The CSS file is inserted where the marker ",Object(o.b)("inlineCode",{parentName:"p"},"/** @@LOADING_CSS@@ **/")," is and the HTML file where ",Object(o.b)("inlineCode",{parentName:"p"},"\x3c!-- @@LOADING_HTML@@ --\x3e")," is."))}b.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return u})),n.d(t,"b",(function(){return m}));var a=n(0),i=n.n(a);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,a,i=function(e,t){if(null==e)return{};var n,a,i={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var c=i.a.createContext({}),b=function(e){var t=i.a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},u=function(e){var t=b(e.components);return i.a.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return i.a.createElement(i.a.Fragment,{},t)}},d=i.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,r=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=b(n),d=a,m=u["".concat(r,".").concat(d)]||u[d]||p[d]||o;return n?i.a.createElement(m,l(l({ref:t},c),{},{components:n})):i.a.createElement(m,l({ref:t},c))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,r=new Array(o);r[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,r[1]=l;for(var c=2;c<o;c++)r[c]=n[c];return i.a.createElement.apply(null,r)}return i.a.createElement.apply(null,n)}d.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/website/site-dist/fdad0c26.0177f981.js b/website/site-dist/fdad0c26.0177f981.js new file mode 100644 index 0000000000..8c06a79837 --- /dev/null +++ b/website/site-dist/fdad0c26.0177f981.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[44],{145:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return i})),n.d(t,"metadata",(function(){return l})),n.d(t,"rightToc",(function(){return c})),n.d(t,"default",(function(){return s}));var a=n(2),r=n(6),o=(n(0),n(149)),i={title:"Frontend Development",sidebar_label:"Overview"},l={id:"developer/frontend",isDocsHomePage:!1,title:"Frontend Development",description:"Introduction to the stack",source:"@site/docs/developer/frontend.md",permalink:"/docs/developer/frontend",editUrl:"https://github.com/cloudfoundry/stratos/edit/master/website/docs/developer/frontend.md",sidebar_label:"Overview",sidebar:"docs",previous:{title:"Developing the Stratos Console",permalink:"/docs/developer/introduction"},next:{title:"Frontend Tests",permalink:"/docs/developer/frontend-tests"}},c=[{value:"Introduction to the stack",id:"introduction-to-the-stack",children:[]},{value:"Set up Dependencies",id:"set-up-dependencies",children:[]},{value:"Configuration",id:"configuration",children:[]},{value:"Run the frontend",id:"run-the-frontend",children:[]},{value:"Build",id:"build",children:[]},{value:"Creating angular items via angular cli",id:"creating-angular-items-via-angular-cli",children:[]},{value:"Theming",id:"theming",children:[]}],p={rightToc:c};function s(e){var t=e.components,n=Object(r.a)(e,["components"]);return Object(o.b)("wrapper",Object(a.a)({},p,n,{components:t,mdxType:"MDXLayout"}),Object(o.b)("h2",{id:"introduction-to-the-stack"},"Introduction to the stack"),Object(o.b)("p",null,"Have a look through the ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"/docs/developer/developers-guide-env-tech"}),"Env + Tech")," page to get acquainted with some of the new technologies used in v2.\nThese include video's, tutorials and examples of Angular 2+, Typescript and Redux. There's also some advice on helpful plugins to use if\nusing Visual Studio Code. If you feel comfortable with these and are happy with your dev environment please skip straight to\n",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"#set-up-dependencies"}),"Set up Dependencies")),Object(o.b)("h2",{id:"set-up-dependencies"},"Set up Dependencies"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Set up a Stratos backend - The frontend cannot run without a backend. Both backend and frontend exist in this same repo.",Object(o.b)("ul",{parentName:"li"},Object(o.b)("li",{parentName:"ul"},"Don't need to make changes to the backend code? To set up a backend run through the ",Object(o.b)("a",Object(a.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/blob/master/deploy/README.md"}),"deploy section"),",\nchoose a deployment method and bring one up. These deployments will bring up the entire backend, including api service and database\nalong with a V2 frontend."),Object(o.b)("li",{parentName:"ul"},"Need to make changes to the backend code? Follow the below ",Object(o.b)("a",Object(a.a)({parentName:"li"},{href:"#Backend-Development"}),"Backend Development")," set up guide"))),Object(o.b)("li",{parentName:"ul"},"Install ",Object(o.b)("a",Object(a.a)({parentName:"li"},{href:"https://nodejs.org"}),"NodeJs")," (minimum node version 12.13.0)"),Object(o.b)("li",{parentName:"ul"},"Install ",Object(o.b)("a",Object(a.a)({parentName:"li"},{href:"https://cli.angular.io/"}),"Angular CLI")," - ",Object(o.b)("inlineCode",{parentName:"li"},"npm install -g @angular/cli"))),Object(o.b)("h2",{id:"configuration"},"Configuration"),Object(o.b)("p",null,"Configuration information can be found in two places"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"./proxy.conf.js"),Object(o.b)("ul",{parentName:"li"},Object(o.b)("li",{parentName:"ul"},"In new forks this is missing and needs to be created using ",Object(o.b)("inlineCode",{parentName:"li"},"./proxy.conf.template.js")," as a template."),Object(o.b)("li",{parentName:"ul"},"Contains the address of the backend. Which will either be...",Object(o.b)("ul",{parentName:"li"},Object(o.b)("li",{parentName:"ul"},"If the backend is deployed via the instructions in the ",Object(o.b)("a",Object(a.a)({parentName:"li"},{href:"https://github.com/cloudfoundry/stratos/blob/master/deploy/README.md"}),"deploy section"),"\nthe url will be the same address as the V1 console's frontend address. For instance ",Object(o.b)("inlineCode",{parentName:"li"},"https://localhost")," would translate to",Object(o.b)("pre",{parentName:"li"},Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),'const PROXY_CONFIG = {\n "/pp": {\n "target": {\n "host": "localhost",\n "protocol": "https:",\n "port": 443\n },\n "secure": false,\n "changeOrigin": true,\n "ws": true,\n}\n'))),Object(o.b)("li",{parentName:"ul"},"If the backend is running locally using the instructions ",Object(o.b)("a",Object(a.a)({parentName:"li"},{href:"#Backend-Development"}),"Backend Development")," below the url will local host\nwith a port of the ",Object(o.b)("inlineCode",{parentName:"li"},"CONSOLE_PROXY_TLS_ADDRESS")," value from ",Object(o.b)("inlineCode",{parentName:"li"},"src/jetstream/config.properties"),". By default this will be 5445. For\ninstance",Object(o.b)("pre",{parentName:"li"},Object(o.b)("code",Object(a.a)({parentName:"pre"},{}),'const PROXY_CONFIG = {\n "/pp": {\n "target": {\n "host": "localhost",\n "protocol": "https:",\n "port": 5443\n },\n "ws": true,\n "secure": false,\n "changeOrigin": true,\n }\n}\n'))))))),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"./src/frontend/environments/environment.ts")," for developer vs production like config",Object(o.b)("ul",{parentName:"li"},Object(o.b)("li",{parentName:"ul"},"This contains more general settings for the frontend and does not usually need to be changed")))),Object(o.b)("h2",{id:"run-the-frontend"},"Run the frontend"),Object(o.b)("ol",null,Object(o.b)("li",{parentName:"ol"},"(First time only) Copy ",Object(o.b)("inlineCode",{parentName:"li"},"./proxy.conf.template.js")," to ",Object(o.b)("inlineCode",{parentName:"li"},"./proxy.conf.js")," and update with required Jetstream url (see above for more info)"),Object(o.b)("li",{parentName:"ol"},"Run ",Object(o.b)("inlineCode",{parentName:"li"},"npm install")),Object(o.b)("li",{parentName:"ol"},"Run ",Object(o.b)("inlineCode",{parentName:"li"},"npm start")," for a dev server. (the app will automatically reload if you change any of the source files)",Object(o.b)("ul",{parentName:"li"},Object(o.b)("li",{parentName:"ul"},"If this times out please use ",Object(o.b)("inlineCode",{parentName:"li"},"npm run start-high-mem")," instead"),Object(o.b)("li",{parentName:"ul"},"To change the port from the default 4200, add ",Object(o.b)("inlineCode",{parentName:"li"},"-- --port [new port number]")),Object(o.b)("li",{parentName:"ul"},"To stop the automatic reload every time a resource changes add ",Object(o.b)("inlineCode",{parentName:"li"},"-- --live-reload false")),Object(o.b)("li",{parentName:"ul"},"To do both the above use ",Object(o.b)("inlineCode",{parentName:"li"},"-- --live-reload false --port [new port number]")))),Object(o.b)("li",{parentName:"ol"},"Navigate to ",Object(o.b)("inlineCode",{parentName:"li"},"https://localhost:4200/"),". The credentials to log in will be dependent on the Jetstream the console points at. Please refer\nto the guides used when setting up the backend for more information")),Object(o.b)("h2",{id:"build"},"Build"),Object(o.b)("p",null,"Run ",Object(o.b)("inlineCode",{parentName:"p"},"npm run build")," to build the project."),Object(o.b)("p",null,"The build artefacts will be stored in the ",Object(o.b)("inlineCode",{parentName:"p"},"dist/")," directory. This will output a production build of the application."),Object(o.b)("h2",{id:"creating-angular-items-via-angular-cli"},"Creating angular items via angular cli"),Object(o.b)("p",null,"To create a new angular component run ",Object(o.b)("inlineCode",{parentName:"p"},"ng generate component component-name"),". You can use a similar command to create other types of angular\nitems ",Object(o.b)("inlineCode",{parentName:"p"},"ng generate <directive|pipe|service|class|guard|interface|enum|module> <name>"),"."),Object(o.b)("h2",{id:"theming"},"Theming"),Object(o.b)("p",null,"We use the angular material theming mechanism. See ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"https://material.angular.io/guide/theming-your-components"}),"here")," for more information about theming new components added to stratos."))}s.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return d})),n.d(t,"b",(function(){return m}));var a=n(0),r=n.n(a);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function c(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=r.a.createContext({}),s=function(e){var t=r.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},d=function(e){var t=s(e.components);return r.a.createElement(p.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},u=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,i=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),d=s(n),u=a,m=d["".concat(i,".").concat(u)]||d[u]||b[u]||o;return n?r.a.createElement(m,l(l({ref:t},p),{},{components:n})):r.a.createElement(m,l({ref:t},p))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=u;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var p=2;p<o;p++)i[p]=n[p];return r.a.createElement.apply(null,i)}return r.a.createElement.apply(null,n)}u.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/website/site-dist/ff53ea4a.ef4116db.js b/website/site-dist/ff53ea4a.ef4116db.js new file mode 100644 index 0000000000..edbd4827ac --- /dev/null +++ b/website/site-dist/ff53ea4a.ef4116db.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[45],{146:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return i})),n.d(t,"metadata",(function(){return l})),n.d(t,"rightToc",(function(){return c})),n.d(t,"default",(function(){return u}));var o=n(2),a=n(6),r=(n(0),n(149)),i={id:"all-in-one",title:"Deploying with the All-In-One Docker Container",sidebar_label:"Docker All-in-One"},l={id:"deploy/all-in-one",isDocsHomePage:!1,title:"Deploying with the All-In-One Docker Container",description:"The all-in-one container sets up the Stratos components in a single container.",source:"@site/docs/deploy/all-in-one.md",permalink:"/docs/deploy/all-in-one",editUrl:"https://github.com/cloudfoundry/stratos/edit/master/website/docs/deploy/all-in-one.md",sidebar_label:"Docker All-in-One",sidebar:"docs",previous:{title:"Deploying Using Helm",permalink:"/docs/deploy/kubernetes/helm-installation"},next:{title:"Accessing Stratos",permalink:"/docs/deploy/access"}},c=[{value:"Requirements:",id:"requirements",children:[]},{value:"Quick Start",id:"quick-start",children:[]},{value:"Note regarding the Stratos Session Store Secret",id:"note-regarding-the-stratos-session-store-secret",children:[]},{value:"Configuring a local user account in place of a UAA",id:"configuring-a-local-user-account-in-place-of-a-uaa",children:[]},{value:"Building the container:",id:"building-the-container",children:[]},{value:"Persisting the Database",id:"persisting-the-database",children:[]},{value:"Pushing the All-In-One Docker Image to Cloud Foundry",id:"pushing-the-all-in-one-docker-image-to-cloud-foundry",children:[]}],s={rightToc:c};function u(e){var t=e.components,n=Object(a.a)(e,["components"]);return Object(r.b)("wrapper",Object(o.a)({},s,n,{components:t,mdxType:"MDXLayout"}),Object(r.b)("p",null,"The all-in-one container sets up the Stratos components in a single container."),Object(r.b)("h2",{id:"requirements"},"Requirements:"),Object(r.b)("p",null,"You will need to have installed Docker, see ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://docs.docker.com/engine/installation/"}),"Docker Installation Documentation"),"."),Object(r.b)("h2",{id:"quick-start"},"Quick Start"),Object(r.b)("p",null,"Run Stratos in Docker locally:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"$ docker run -p 4443:443 splatform/stratos:latest \n")),Object(r.b)("p",null,"Once that has finished, you can then access Stratos by visiting ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://localhost:4443"}),"https://localhost:4443"),"."),Object(r.b)("p",null,"You can configure a local admin account and set the password for future logins."),Object(r.b)("h2",{id:"note-regarding-the-stratos-session-store-secret"},"Note regarding the Stratos Session Store Secret"),Object(r.b)("p",null,"Stratos uses a secret to protect the Session cookie it uses to identify users. By default it will generate a random value for this secret."),Object(r.b)("p",null,"We recommend configuring an alphanumeric secret of your choice by setting the ",Object(r.b)("inlineCode",{parentName:"p"},"SESSION_STORE_SECRET")," environment variable."),Object(r.b)("p",null,"This can be done by adding the following to the docker run command shown in the section below:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"-e SESSION_STORE_SECRET=<alphanumeric secret>\n")),Object(r.b)("h2",{id:"configuring-a-local-user-account-in-place-of-a-uaa"},"Configuring a local user account in place of a UAA"),Object(r.b)("p",null,"By default the All-in-one image requires a UAA for user authentication. If this is not desired, the image can be configured to use a Stratos local user account. Edit the file ",Object(r.b)("inlineCode",{parentName:"p"},"deploy/all-in-one/config.all-in-one.properties")," and uncomment the following lines before building the container."),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"#AUTH_ENDPOINT_TYPE=local\n#LOCAL_USER=localuser\n#LOCAL_USER_PASSWORD=localuserpass\n#LOCAL_USER_SCOPE=stratos.admin\n")),Object(r.b)("h2",{id:"building-the-container"},"Building the container:"),Object(r.b)("p",null,"To build the container, change directory to the root of the project and open a command prompt:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"build/store-git-metadata.sh\ndocker build -f deploy/Dockerfile.all-in-one . -t stratos-aio\n")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: The Dockerfile for all-in-one is in the ",Object(r.b)("inlineCode",{parentName:"p"},"deploy")," folder and not the ",Object(r.b)("inlineCode",{parentName:"p"},"deploy/all-in-one")," folder.")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: If you are using Docker for Mac and you get an error 137 when building, you should increase the memory available to Docker (via Preferences > Advanced) and try again.")),Object(r.b)("p",null,"Bring up the container with:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"docker run -p 4443:443 stratos-aio\n")),Object(r.b)("p",null,"Stratos should now be accessible at the following URL:"),Object(r.b)("p",null,"https://localhost:4443"),Object(r.b)("p",null,"If using a UAA, you will be presented with the Stratos Setup welcome screen - you will need to enter your UAA information to configure Stratos. Once complete, you will be able to login with your credentials. If you have configured the container to use a local user account instead of a UAA, log in with the credentials specified in the configuration file."),Object(r.b)("h2",{id:"persisting-the-database"},"Persisting the Database"),Object(r.b)("p",null,"Each time you start and stop the Docker All-In-One container, you will lose any your UAA configuration, endpoints and connections that you have made in Stratos."),Object(r.b)("p",null,"In order to persist the Stratos database file between runs of the Docker container you can store the database file outside of the docker container."),Object(r.b)("p",null,"Create a folder where the database folder will be stored, e.g."),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"mkdir -p ~/stratos-db\n")),Object(r.b)("p",null,"When starting the Docker container, mount a volume for this folder and pass this via the ",Object(r.b)("inlineCode",{parentName:"p"},"SQLITE_DB_DIR")," environment variable, e.g."),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"docker run -p 4443:443 -v ~/stratos-db:/var/stratos-db -e SQLITE_DB_DIR=/var/stratos-db stratos-aio\n")),Object(r.b)("p",null,"Now each time you stop and start the container, Stratos will maintain the database file."),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: You can validate that the environment variable has been correctly set and check the database file location by observing the log file\nof the Docker container. You should see a log message similar to: ",Object(r.b)("inlineCode",{parentName:"p"},"SQLite Database file: /var/stratos-db/console-database.db"))),Object(r.b)("h2",{id:"pushing-the-all-in-one-docker-image-to-cloud-foundry"},"Pushing the All-In-One Docker Image to Cloud Foundry"),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: We recommend setting the session store secret - please use a manifest file for this and set the ",Object(r.b)("inlineCode",{parentName:"p"},"SESSION_STORE_SECRET")," environment variable.")),Object(r.b)("p",null,"The All-In-One Docker Image can be pushed to Cloud Foundry."),Object(r.b)("p",null,"Firstly, build the image and push it to a Docker registry, so that it is available to Cloud Foundry, e.g. to build and push to Docker Hub, in the project root directory run:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"build/store-git-metadata.sh\ndocker build -f deploy/Dockerfile.all-in-one . -t MY-DOCKER-ORG/stratos-aio:latest\ndocker push MY-DOCKER-ORG/stratos-aio:latest\n")),Object(r.b)("p",null,"Where ",Object(r.b)("inlineCode",{parentName:"p"},"MY-DOCKER_ORG")," is your Docker Hub organization."),Object(r.b)("p",null,"You can now push this image directly to Cloud Foundry with:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"cf push stratos --docker-image MY-DOCKER-ORG/stratos-aio:latest\n")),Object(r.b)("p",null,"The log output of the push command will include the URL where the Stratos application can be accessed in a browser, e.g."),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),"> cf push stratos --docker-image MY-DOCKER-ORG/stratos-aio:latest\nCreating app stratos in org e2e / space e2e as admin...\nOK\n\nCreating route stratos.local.pcfdev.io...\nOK\n\nBinding stratos.local.pcfdev.io to stratos...\nOK\n\n\nStarting app stratos in org e2e / space e2e as admin...\nCreating container\nSuccessfully created container\nStaging...\nStaging process started ...\nStaging process finished\nExit status 0\nStaging Complete\nDestroying container\nSuccessfully destroyed container\n\n1 of 1 instances running\n\nApp started\n\n\nOK\n\nApp stratos was started using this command `./jetstream `\n\nShowing health and status for app stratos in org e2e / space e2e as admin...\nOK\n\nrequested state: started\ninstances: 1/1\nusage: 256M x 1 instances\nurls: stratos.local.pcfdev.io <-- URL\nlast uploaded: Mon Dec 3 03:12:47 UTC 2018\nstack: cflinuxfs2\nbuildpack: unknown\n\n state since cpu memory disk details\n#0 running 2018-12-03 03:12:54 AM 0.0% 0 of 256M 0 of 512M\n")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: In this example we are pushing with the application name ",Object(r.b)("inlineCode",{parentName:"p"},"stratos"))),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"Note: By default the All-in-one image has SSL Validation disabled when authenticating with Cloud Foundry and the UAA - this allows it to work out of the box with environments like PCF Dev. If this is not the behavior you desire, edit the file ",Object(r.b)("inlineCode",{parentName:"p"},"deploy/all-in-one/config.all-in-one.properties")," and change the ",Object(r.b)("inlineCode",{parentName:"p"},"SKIP_SSL_VALIDATION")," as desired before building and publishing the image.")))}u.isMDXComponent=!0},149:function(e,t,n){"use strict";n.d(t,"a",(function(){return b})),n.d(t,"b",(function(){return h}));var o=n(0),a=n.n(o);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function c(e,t){if(null==e)return{};var n,o,a=function(e,t){if(null==e)return{};var n,o,a={},r=Object.keys(e);for(o=0;o<r.length;o++)n=r[o],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o<r.length;o++)n=r[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=a.a.createContext({}),u=function(e){var t=a.a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},b=function(e){var t=u(e.components);return a.a.createElement(s.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},p=a.a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,i=e.parentName,s=c(e,["components","mdxType","originalType","parentName"]),b=u(n),p=o,h=b["".concat(i,".").concat(p)]||b[p]||d[p]||r;return n?a.a.createElement(h,l(l({ref:t},s),{},{components:n})):a.a.createElement(h,l({ref:t},s))}));function h(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,i=new Array(r);i[0]=p;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var s=2;s<r;s++)i[s]=n[s];return a.a.createElement.apply(null,i)}return a.a.createElement.apply(null,n)}p.displayName="MDXCreateElement"}}]); \ No newline at end of file diff --git a/website/site-dist/images/Browserstack-logo.svg b/website/site-dist/images/Browserstack-logo.svg new file mode 100644 index 0000000000..195f64d2fe --- /dev/null +++ b/website/site-dist/images/Browserstack-logo.svg @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 490.1 105.6" style="enable-background:new 0 0 490.1 105.6;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#F4B960;} + .st1{fill:#E66F32;} + .st2{fill:#E43C41;} + .st3{fill:#BDD041;} + .st4{fill:#6DB54C;} + .st5{fill:#AEDAE6;} + .st6{fill:#56B8DE;} + .st7{fill:#00B1D5;} + .st8{fill:url(#SVGID_1_);} + .st9{fill:#221F1F;} + .st10{fill:#FFFFFF;} + .st11{fill:#000111;} +</style> +<title>Browserstack-logo-white + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/site-dist/images/extensions/app-tab-example.png b/website/site-dist/images/extensions/app-tab-example.png new file mode 100644 index 0000000000..dad460e413 Binary files /dev/null and b/website/site-dist/images/extensions/app-tab-example.png differ diff --git a/website/site-dist/images/extensions/appwall-action-example.png b/website/site-dist/images/extensions/appwall-action-example.png new file mode 100644 index 0000000000..0a62249800 Binary files /dev/null and b/website/site-dist/images/extensions/appwall-action-example.png differ diff --git a/website/site-dist/images/extensions/tab-example.png b/website/site-dist/images/extensions/tab-example.png new file mode 100644 index 0000000000..38afc322b7 Binary files /dev/null and b/website/site-dist/images/extensions/tab-example.png differ diff --git a/website/site-dist/images/high-level-arch.png b/website/site-dist/images/high-level-arch.png new file mode 100644 index 0000000000..01285d6303 Binary files /dev/null and b/website/site-dist/images/high-level-arch.png differ diff --git a/website/site-dist/images/screenshots/app-summary.png b/website/site-dist/images/screenshots/app-summary.png new file mode 100644 index 0000000000..0a1d7be660 Binary files /dev/null and b/website/site-dist/images/screenshots/app-summary.png differ diff --git a/website/site-dist/img/cloudfoundry.png b/website/site-dist/img/cloudfoundry.png new file mode 100644 index 0000000000..378a74380f Binary files /dev/null and b/website/site-dist/img/cloudfoundry.png differ diff --git a/website/site-dist/img/deploy.svg b/website/site-dist/img/deploy.svg new file mode 100644 index 0000000000..097f164ef5 --- /dev/null +++ b/website/site-dist/img/deploy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/site-dist/img/easy.svg b/website/site-dist/img/easy.svg new file mode 100644 index 0000000000..1e32c1c49d --- /dev/null +++ b/website/site-dist/img/easy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/site-dist/img/extend.svg b/website/site-dist/img/extend.svg new file mode 100644 index 0000000000..3c4cbcf5ee --- /dev/null +++ b/website/site-dist/img/extend.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/site-dist/img/favicon.ico b/website/site-dist/img/favicon.ico new file mode 100644 index 0000000000..21f49bc43b Binary files /dev/null and b/website/site-dist/img/favicon.ico differ diff --git a/website/site-dist/img/kubernetes.svg b/website/site-dist/img/kubernetes.svg new file mode 100644 index 0000000000..bd6b1464fe --- /dev/null +++ b/website/site-dist/img/kubernetes.svg @@ -0,0 +1,84 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + \ No newline at end of file diff --git a/website/site-dist/img/logo.png b/website/site-dist/img/logo.png new file mode 100644 index 0000000000..03d4990b89 Binary files /dev/null and b/website/site-dist/img/logo.png differ diff --git a/website/site-dist/img/logo.svg b/website/site-dist/img/logo.svg new file mode 100644 index 0000000000..9db6d0d066 --- /dev/null +++ b/website/site-dist/img/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/site-dist/img/multi-cluster.svg b/website/site-dist/img/multi-cluster.svg new file mode 100644 index 0000000000..ad663a1212 --- /dev/null +++ b/website/site-dist/img/multi-cluster.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/website/site-dist/img/open-source.svg b/website/site-dist/img/open-source.svg new file mode 100644 index 0000000000..c40cc14486 --- /dev/null +++ b/website/site-dist/img/open-source.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/site-dist/img/screens/cf-app.png b/website/site-dist/img/screens/cf-app.png new file mode 100644 index 0000000000..447fdada88 Binary files /dev/null and b/website/site-dist/img/screens/cf-app.png differ diff --git a/website/site-dist/img/screens/endpoints.png b/website/site-dist/img/screens/endpoints.png new file mode 100644 index 0000000000..5abf20fc94 Binary files /dev/null and b/website/site-dist/img/screens/endpoints.png differ diff --git a/website/site-dist/img/screens/kube-graph.png b/website/site-dist/img/screens/kube-graph.png new file mode 100644 index 0000000000..5d0ad09bde Binary files /dev/null and b/website/site-dist/img/screens/kube-graph.png differ diff --git a/website/site-dist/index.html b/website/site-dist/index.html new file mode 100644 index 0000000000..18a4efbe98 --- /dev/null +++ b/website/site-dist/index.html @@ -0,0 +1,25 @@ + + + + + + +Home | STRATOS + + + + + + + + +
+

STRATOS

Open-Source Multi-Cluster UI for
Cloud Foundry and Kubernetes

Cloud Foundry

Stratos is the de-facto UI for Cloud Foundry, providing a rich management experience for all you Cloud Foundry needs... and we're an offical Cloud Foundry project too!

[object Object]

Kubernetes

Stratos sports a growing feature set for Kubernetes developers, extending its reach further towards providing a single-pane-of-glass for your Cloud Native application development needs.

[object Object]

Multi-Cluster

Stratos allows you to manage multiple Cloud Foundry and Kubernetes cluster from a single management UI

[object Object]

Extensible

Stratos is built with extensibility in mind and we continue to expand and improve the extensibility experience for developers

[object Object]

Open Source

Stratos is Open Source with an Apache 2.0 License. Our codes lives on GitHub and we're a project within the Cloud Foundry Foundation

[object Object]

Easy to Deploy

Stratos is easy to deploy and can be pushed as an application to Cloud Foundry, deployed to Kubernetes using Helm or run locally in a Docker container

Cloud Foundry

Deploy and manage applications in Cloud Foundry. Stream application logs, scale applications and ssh to application instances

View and manage Cloud Foundry organizations and spaces and quotas.

Browse the Service Marketplace and create and manage service instances.

and a whole lot more ...

Kubernetes

View cluster-level metadata

Browse, view and install Helm Charts

View Helm Releases and see relationships between Kubernetes Resources

and lots more ...

Multi-Cluster

Add and Connect multiple Cloud Foundry and/or Kubernetes clusters.

Seemlessly switch between clusters and get aggregated views across clusters.

Favorite clusters and entities for easy access from the Home screen.

+ + + + + + + + \ No newline at end of file diff --git a/website/site-dist/main.8d981086.js b/website/site-dist/main.8d981086.js new file mode 100644 index 0000000000..d1f23fe335 --- /dev/null +++ b/website/site-dist/main.8d981086.js @@ -0,0 +1,2 @@ +/*! For license information please see main.8d981086.js.LICENSE.txt */ +(window.webpackJsonp=window.webpackJsonp||[]).push([[46],[function(e,t,n){"use strict";e.exports=n(54)},function(e,t,n){"use strict";n.d(t,"a",(function(){return k})),n.d(t,"b",(function(){return b})),n.d(t,"c",(function(){return C})),n.d(t,"d",(function(){return g})),n.d(t,"e",(function(){return w})),n.d(t,"f",(function(){return A})),n.d(t,"g",(function(){return O}));var r=n(3),o=n(0),i=n.n(o),a=(n(9),n(5)),l=n(33),u=n(4),s=n(2),c=n(34),d=n.n(c),f=(n(47),n(6)),p=n(51),m=n.n(p),h=function(e){var t=Object(l.a)();return t.displayName=e,t}("Router-History"),g=function(e){var t=Object(l.a)();return t.displayName=e,t}("Router"),b=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,t.staticContext||(n.unlisten=t.history.listen((function(e){n._isMounted?n.setState({location:e}):n._pendingLocation=e}))),n}Object(r.a)(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){this._isMounted=!0,this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&this.unlisten()},n.render=function(){return i.a.createElement(g.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},i.a.createElement(h.Provider,{children:this.props.children||null,value:this.props.history}))},t}(i.a.Component);i.a.Component;i.a.Component;var v={},y=0;function w(e,t){void 0===t&&(t={}),("string"==typeof t||Array.isArray(t))&&(t={path:t});var n=t,r=n.path,o=n.exact,i=void 0!==o&&o,a=n.strict,l=void 0!==a&&a,u=n.sensitive,s=void 0!==u&&u;return[].concat(r).reduce((function(t,n){if(!n&&""!==n)return null;if(t)return t;var r=function(e,t){var n=""+t.end+t.strict+t.sensitive,r=v[n]||(v[n]={});if(r[e])return r[e];var o=[],i={regexp:d()(e,o,t),keys:o};return y<1e4&&(r[e]=i,y++),i}(n,{end:i,strict:l,sensitive:s}),o=r.regexp,a=r.keys,u=o.exec(e);if(!u)return null;var c=u[0],f=u.slice(1),p=e===c;return i&&!p?null:{path:n,url:"/"===n&&""===c?"/":c,isExact:p,params:a.reduce((function(e,t,n){return e[t.name]=f[n],e}),{})}}),null)}var k=function(e){function t(){return e.apply(this,arguments)||this}return Object(r.a)(t,e),t.prototype.render=function(){var e=this;return i.a.createElement(g.Consumer,null,(function(t){t||Object(u.a)(!1);var n=e.props.location||t.location,r=e.props.computedMatch?e.props.computedMatch:e.props.path?w(n.pathname,e.props):t.match,o=Object(s.a)({},t,{location:n,match:r}),a=e.props,l=a.children,c=a.component,d=a.render;return Array.isArray(l)&&0===l.length&&(l=null),i.a.createElement(g.Provider,{value:o},o.match?l?"function"==typeof l?l(o):l:c?i.a.createElement(c,o):d?d(o):null:"function"==typeof l?l(o):null)}))},t}(i.a.Component);function E(e){return"/"===e.charAt(0)?e:"/"+e}function x(e,t){if(!e)return t;var n=E(e);return 0!==t.pathname.indexOf(n)?t:Object(s.a)({},t,{pathname:t.pathname.substr(n.length)})}function S(e){return"string"==typeof e?e:Object(a.e)(e)}function T(e){return function(){Object(u.a)(!1)}}function _(){}i.a.Component;var C=function(e){function t(){return e.apply(this,arguments)||this}return Object(r.a)(t,e),t.prototype.render=function(){var e=this;return i.a.createElement(g.Consumer,null,(function(t){t||Object(u.a)(!1);var n,r,o=e.props.location||t.location;return i.a.Children.forEach(e.props.children,(function(e){if(null==r&&i.a.isValidElement(e)){n=e;var a=e.props.path||e.props.from;r=a?w(o.pathname,Object(s.a)({},e.props,{path:a})):t.match}})),r?i.a.cloneElement(n,{location:o,computedMatch:r}):null}))},t}(i.a.Component);function O(e){var t="withRouter("+(e.displayName||e.name)+")",n=function(t){var n=t.wrappedComponentRef,r=Object(f.a)(t,["wrappedComponentRef"]);return i.a.createElement(g.Consumer,null,(function(t){return t||Object(u.a)(!1),i.a.createElement(e,Object(s.a)({},r,t,{ref:n}))}))};return n.displayName=t,n.WrappedComponent=e,m()(n,e)}var P=i.a.useContext;function A(){return P(g).location}},function(e,t,n){"use strict";function r(){return(r=Object.assign||function(e){for(var t=1;t=0;f--){var p=a[f];"."===p?i(a,f):".."===p?(i(a,f),d++):d&&(i(a,f),d--)}if(!s)for(;d--;d)a.unshift("..");!s||""===a[0]||a[0]&&o(a[0])||a.unshift("");var m=a.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};function l(e){return e.valueOf?e.valueOf():Object.prototype.valueOf.call(e)}var u=function e(t,n){if(t===n)return!0;if(null==t||null==n)return!1;if(Array.isArray(t))return Array.isArray(n)&&t.length===n.length&&t.every((function(t,r){return e(t,n[r])}));if("object"==typeof t||"object"==typeof n){var r=l(t),o=l(n);return r!==t||o!==n?e(r,o):Object.keys(Object.assign({},t,n)).every((function(r){return e(t[r],n[r])}))}return!1},s=n(4);function c(e){return"/"===e.charAt(0)?e:"/"+e}function d(e){return"/"===e.charAt(0)?e.substr(1):e}function f(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function p(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function m(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function h(e,t,n,o){var i;"string"==typeof e?(i=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var i=t.indexOf("?");return-1!==i&&(n=t.substr(i),t=t.substr(0,i)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e)).state=t:(void 0===(i=Object(r.a)({},e)).pathname&&(i.pathname=""),i.search?"?"!==i.search.charAt(0)&&(i.search="?"+i.search):i.search="",i.hash?"#"!==i.hash.charAt(0)&&(i.hash="#"+i.hash):i.hash="",void 0!==t&&void 0===i.state&&(i.state=t));try{i.pathname=decodeURI(i.pathname)}catch(l){throw l instanceof URIError?new URIError('Pathname "'+i.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):l}return n&&(i.key=n),o?i.pathname?"/"!==i.pathname.charAt(0)&&(i.pathname=a(i.pathname,o.pathname)):i.pathname=o.pathname:i.pathname||(i.pathname="/"),i}function g(e,t){return e.pathname===t.pathname&&e.search===t.search&&e.hash===t.hash&&e.key===t.key&&u(e.state,t.state)}function b(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var i="function"==typeof e?e(t,n):e;"string"==typeof i?"function"==typeof r?r(i,o):o(!0):o(!1!==i)}else o(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,r):n.push(r),d({action:"PUSH",location:r,index:t,entries:n})}}))},replace:function(e,t){var r=h(e,t,f(),w.location);c.confirmTransitionTo(r,"REPLACE",n,(function(e){e&&(w.entries[w.index]=r,d({action:"REPLACE",location:r}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=w.index+e;return t>=0&&t=0||(o[n]=e[n]);return o}n.d(t,"a",(function(){return r}))},function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t,n){var r=n(24),o=n(40);e.exports=n(13)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){e.exports=n(80)()},function(e,t,n){"use strict";n.d(t,"a",(function(){return l})),n.d(t,"b",(function(){return u}));var r=n(1),o=n(2),i=n(0),a=n.n(i);function l(e,t,n){return void 0===n&&(n=[]),e.some((function(e){var o=e.path?Object(r.e)(t,e):n.length?n[n.length-1].match:r.b.computeRootMatch(t);return o&&(n.push({route:e,match:o}),e.routes&&l(e.routes,t,n)),o})),n}function u(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),e?a.a.createElement(r.c,n,e.map((function(e,n){return a.a.createElement(r.a,{key:e.key||n,path:e.path,exact:e.exact,strict:e.strict,render:function(n){return e.render?e.render(Object(o.a)({},n,{},t,{route:e})):a.a.createElement(e.component,Object(o.a)({},n,t,{route:e}))}})}))):null}},function(e,t,n){var r=n(21)("wks"),o=n(23),i=n(7).Symbol,a="function"==typeof i;(e.exports=function(e){return r[e]||(r[e]=a&&i[e]||(a?i:o)("Symbol."+e))}).store=r},function(e,t,n){for(var r=n(58),o=n(42),i=n(29),a=n(7),l=n(8),u=n(27),s=n(11),c=s("iterator"),d=s("toStringTag"),f=u.Array,p={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},m=o(p),h=0;h
'};function o(e,t,n){return en?n:e}function i(e){return 100*(-1+e)}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=o(e,r.minimum,1),n.status=1===e?null:e;var u=n.render(!t),s=u.querySelector(r.barSelector),c=r.speed,d=r.easing;return u.offsetWidth,a((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),l(s,function(e,t,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+i(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+i(e)+"%,0)"}:{"margin-left":i(e)+"%"}).transition="all "+t+"ms "+n,o}(e,c,d)),1===e?(l(u,{transition:"none",opacity:1}),u.offsetWidth,setTimeout((function(){l(u,{transition:"all "+c+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),c)}),c)):setTimeout(t,c)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*o(Math.random()*t,.1,.95)),t=o(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");s(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var o,a=t.querySelector(r.barSelector),u=e?"-100":i(n.status||0),c=document.querySelector(r.parent);return l(a,{transition:"all 0 linear",transform:"translate3d("+u+"%,0,0)"}),r.showSpinner||(o=t.querySelector(r.spinnerSelector))&&f(o),c!=document.body&&s(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){c(document.documentElement,"nprogress-busy"),c(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var a=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(n){return n=n.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()})),t[n]||(t[n]=function(t){var n=document.body.style;if(t in n)return t;for(var r,o=e.length,i=t.charAt(0).toUpperCase()+t.slice(1);o--;)if((r=e[o]+i)in n)return r;return t}(n))}function r(e,t,r){t=n(t),e.style[t]=r}return function(e,t){var n,o,i=arguments;if(2==i.length)for(n in t)void 0!==(o=t[n])&&t.hasOwnProperty(n)&&r(e,n,o);else r(e,i[1],i[2])}}();function u(e,t){return("string"==typeof e?e:d(e)).indexOf(" "+t+" ")>=0}function s(e,t){var n=d(e),r=n+t;u(n,t)||(e.className=r.substring(1))}function c(e,t){var n,r=d(e);u(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function d(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n})?r.call(t,n,t,e):r)||(e.exports=o)},function(e,t,n){"use strict";n.d(t,"a",(function(){return d})),n.d(t,"b",(function(){return b})),n.d(t,"c",(function(){return w}));var r=n(1);n.d(t,"d",(function(){return r.e})),n.d(t,"e",(function(){return r.f}));var o=n(3),i=n(0),a=n.n(i),l=n(5),u=(n(9),n(2)),s=n(6),c=n(4),d=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;oe.length)return;if(!(k instanceof u)){if(h&&y!=t.length-1){if(f.lastIndex=w,!(C=f.exec(e)))break;for(var E=C.index+(m?C[1].length:0),x=C.index+C[0].length,S=y,T=w,_=t.length;S<_&&(T=(T+=t[S].length)&&(++y,w=T);if(t[y]instanceof u)continue;O=S-y,k=e.slice(w,T),C.index-=w}else{f.lastIndex=0;var C=f.exec(k),O=1}if(C){m&&(g=C[1]?C[1].length:0),x=(E=C.index+g)+(C=C[0].slice(g)).length;var P=k.slice(0,E),A=k.slice(x),R=[y,O];P&&(++y,w+=P.length,R.push(P));var N=new u(s,p?o.tokenize(C,p):C,b,C,h);if(R.push(N),A&&R.push(A),Array.prototype.splice.apply(t,R),1!=O&&o.matchGrammar(e,t,n,y,w,!0,s),a)break}else if(a)break}}}}},hooks:{add:function(){}},tokenize:function(e,t,n){var r=[e],i=t.rest;if(i){for(var a in i)t[a]=i[a];delete t.rest}return o.matchGrammar(e,r,t,0,0,!1),r}},(i=o.Token=function(e,t,n,r,o){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length,this.greedy=!!o}).stringify=function(e,t,n){if("string"==typeof e)return e;if("Array"===o.util.type(e))return e.map((function(n){return i.stringify(n,t,e)})).join("");var r={type:e.type,content:i.stringify(e.content,t,n),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:n};if(e.alias){var a="Array"===o.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(r.classes,a)}var l=Object.keys(r.attributes).map((function(e){return e+'="'+(r.attributes[e]||"").replace(/"/g,""")+'"'})).join(" ");return"<"+r.tag+' class="'+r.classes.join(" ")+'"'+(l?" "+l:"")+">"+r.content+""},o);a.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},a.languages.markup.tag.inside["attr-value"].inside.entity=a.languages.markup.entity,a.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(a.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:a.languages[t]},n.cdata=/^$/i;var r={"included-cdata":{pattern://i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:a.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[\s\S]*?>)(?:\s*|[\s\S])*?(?=<\/__>)/.source.replace(/__/g,e),"i"),lookbehind:!0,greedy:!0,inside:r},a.languages.insertBefore("markup","cdata",o)}}),a.languages.xml=a.languages.extend("markup",{}),a.languages.html=a.languages.markup,a.languages.mathml=a.languages.markup,a.languages.svg=a.languages.markup,function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)\w+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b\w+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+?)\s*(?:\r?\n|\r)(?:[\s\S])*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:n},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s*(?:\r?\n|\r)(?:[\s\S])*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0},{pattern:/(["'])(?:\\[\s\S]|\$\([^)]+\)|`[^`]+`|(?!\1)[^\\])*\1/,greedy:!0,inside:n}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:n.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|aptitude|apt-cache|apt-get|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:if|then|else|elif|fi|for|while|in|case|esac|function|select|do|done|until)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|break|cd|continue|eval|exec|exit|export|getopts|hash|pwd|readonly|return|shift|test|times|trap|umask|unset|alias|bind|builtin|caller|command|declare|echo|enable|help|let|local|logout|mapfile|printf|read|readarray|source|type|typeset|ulimit|unalias|set|shopt)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:true|false)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|==?|!=?|=~|<<[<-]?|[&\d]?>>|\d?[<>]&?|&[>&]?|\|[&|]?|<=?|>=?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}};for(var r=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=n.variable[1].inside,i=0;i=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/},a.languages.c=a.languages.extend("clike",{"class-name":{pattern:/(\b(?:enum|struct)\s+)\w+/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/,number:/(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),a.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete a.languages.c.boolean,a.languages.cpp=a.languages.extend("c",{"class-name":{pattern:/(\b(?:class|enum|struct)\s+)\w+/,lookbehind:!0},keyword:/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+\.?[\da-f']*|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+\.?[\d']*|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]*/i,greedy:!0},operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),a.languages.insertBefore("cpp","string",{"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),function(e){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/@[\w-]+/}},url:{pattern:RegExp("url\\((?:"+t.source+"|[^\n\r()]*)\\)","i"),inside:{function:/^url/i,punctuation:/^\(|\)$/}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+t.source+")*?(?=\\s*\\{)"),string:{pattern:t,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),e.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:n.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:e.languages.css}},alias:"language-css"}},n.tag))}(a),a.languages.css.selector={pattern:a.languages.css.selector,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-:.\w]+/,id:/#[-:.\w]+/,attribute:{pattern:/\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)*\]/,greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)[-*\w\xA0-\uFFFF]*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},attribute:{pattern:/^(\s*)[-\w\xA0-\uFFFF]+/,lookbehind:!0},value:[/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,{pattern:/(=\s*)[-\w\xA0-\uFFFF]+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],punctuation:/[()]/}},a.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i,lookbehind:!0}}),a.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:/#[\da-f]{3,8}/i,entity:/\\[\da-f]{1,8}/i,unit:{pattern:/(\d)(?:%|[a-z]+)/,lookbehind:!0},number:/-?[\d.]+/}),a.languages.javascript=a.languages.extend("clike",{"class-name":[a.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.])\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),a.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,a.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:a.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:a.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:a.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:a.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),a.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:a.languages.javascript}},string:/[\s\S]+/}}}),a.languages.markup&&a.languages.markup.tag.addInlined("script","javascript"),a.languages.js=a.languages.javascript,function(e){var t=e.util.clone(e.languages.javascript);e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=/<\/?(?:[\w.:-]+\s*(?:\s+(?:[\w.:-]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s{'">=]+|\{(?:\{(?:\{[^}]*\}|[^{}])*\}|[^{}])+\}))?|\{\.{3}[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\}))*\s*\/?)?>/i,e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/i,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">]+)/i,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.insertBefore("inside","attr-name",{spread:{pattern:/\{\.{3}[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\}/,inside:{punctuation:/\.{3}|[{}.]/,"attr-value":/\w+/}}},e.languages.jsx.tag),e.languages.insertBefore("inside","attr-value",{script:{pattern:/=(\{(?:\{(?:\{[^}]*\}|[^}])*\}|[^}])+\})/i,inside:{"script-punctuation":{pattern:/^=(?={)/,alias:"punctuation"},rest:e.languages.jsx},alias:"language-javascript"}},e.languages.jsx.tag);var n=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(n).join(""):""},r=function(t){for(var o=[],i=0;i0&&o[o.length-1].tagName===n(a.content[0].content[1])&&o.pop():"/>"===a.content[a.content.length-1].content||o.push({tagName:n(a.content[0].content[1]),openedBraces:0}):o.length>0&&"punctuation"===a.type&&"{"===a.content?o[o.length-1].openedBraces++:o.length>0&&o[o.length-1].openedBraces>0&&"punctuation"===a.type&&"}"===a.content?o[o.length-1].openedBraces--:l=!0),(l||"string"==typeof a)&&o.length>0&&0===o[o.length-1].openedBraces){var u=n(a);i0&&("string"==typeof t[i-1]||"plain-text"===t[i-1].type)&&(u=n(t[i-1])+u,t.splice(i-1,1),i--),t[i]=new e.Token("plain-text",u,null,u)}a.content&&"string"!=typeof a.content&&r(a.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||r(e.tokens)}))}(a),function(e){var t=e.languages.javadoclike={parameter:{pattern:/(^\s*(?:\/{3}|\*|\/\*\*)\s*@(?:param|arg|arguments)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^\s*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};Object.defineProperty(t,"addSupport",{value:function(t,n){"string"==typeof t&&(t=[t]),t.forEach((function(t){!function(t,n){var r=e.languages[t];if(r){var o=r["doc-comment"];if(!o){var i={"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,alias:"comment"}};o=(r=e.languages.insertBefore(t,"comment",i))["doc-comment"]}if(o instanceof RegExp&&(o=r["doc-comment"]={pattern:o}),Array.isArray(o))for(var a=0,l=o.length;a>>?=?|->|([-+&|])\2|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","class-name",{annotation:{alias:"punctuation",pattern:/(^|[^.])@\w+/,lookbehind:!0},namespace:{pattern:/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)[a-z]\w*(\.[a-z]\w*)+/,lookbehind:!0,inside:{punctuation:/\./}},generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":n,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})}(a),function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,o,i){if(n.language===r){var a=n.tokenStack=[];n.code=n.code.replace(o,(function(e){if("function"==typeof i&&!i(e))return e;for(var o,l=a.length;-1!==n.code.indexOf(o=t(r,l));)++l;return a[l]=e,o})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var o=0,i=Object.keys(n.tokenStack);!function a(l){for(var u=0;u=i.length);u++){var s=l[u];if("string"==typeof s||s.content&&"string"==typeof s.content){var c=i[o],d=n.tokenStack[c],f="string"==typeof s?s:s.content,p=t(r,c),m=f.indexOf(p);if(m>-1){++o;var h=f.substring(0,m),g=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),b=f.substring(m+p.length),v=[];h&&v.push.apply(v,a([h])),v.push(g),b&&v.push.apply(v,a([b])),"string"==typeof s?l.splice.apply(l,[u,1].concat(v)):s.content=v}}else s.content&&a(s.content)}return l}(n.tokens)}}}})}(a),function(e){e.languages.php=e.languages.extend("clike",{keyword:/\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|new|or|parent|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,boolean:{pattern:/\b(?:false|true)\b/i,alias:"constant"},constant:[/\b[A-Z_][A-Z0-9_]*\b/,/\b(?:null)\b/i],comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0}}),e.languages.insertBefore("php","string",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),e.languages.insertBefore("php","comment",{delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"}}),e.languages.insertBefore("php","keyword",{variable:/\$+(?:\w+\b|(?={))/i,package:{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),e.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}});var t={pattern:/{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/,lookbehind:!0,inside:{rest:e.languages.php}};e.languages.insertBefore("php","string",{"nowdoc-string":{pattern:/<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},"heredoc-string":{pattern:/<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:t}},"single-quoted-string":{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0,alias:"string"},"double-quoted-string":{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,alias:"string",inside:{interpolation:t}}}),delete e.languages.php.string,e.hooks.add("before-tokenize",(function(t){if(/<\?/.test(t.code)){e.languages["markup-templating"].buildPlaceholders(t,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#)(?:[^?\n\r]|\?(?!>))*|\/\*[\s\S]*?(?:\*\/|$))*?(?:\?>|$)/gi)}})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"php")}))}(a),function(e){var t=e.languages.javascript,n=/{(?:[^{}]|{(?:[^{}]|{[^{}]*})*})+}/.source,r="(@(?:param|arg|argument|property)\\s+(?:"+n+"\\s+)?)";e.languages.jsdoc=e.languages.extend("javadoclike",{parameter:{pattern:RegExp(r+/[$\w\xA0-\uFFFF.]+(?=\s|$)/.source),lookbehind:!0,inside:{punctuation:/\./}}}),e.languages.insertBefore("jsdoc","keyword",{"optional-parameter":{pattern:RegExp(r+/\[[$\w\xA0-\uFFFF.]+(?:=[^[\]]+)?\](?=\s|$)/.source),lookbehind:!0,inside:{parameter:{pattern:/(^\[)[$\w\xA0-\uFFFF\.]+/,lookbehind:!0,inside:{punctuation:/\./}},code:{pattern:/(=)[\s\S]*(?=\]$)/,lookbehind:!0,inside:t,alias:"language-javascript"},punctuation:/[=[\]]/}},"class-name":[{pattern:RegExp("(@[a-z]+\\s+)"+n),lookbehind:!0,inside:{punctuation:/[.,:?=<>|{}()[\]]/}},{pattern:/(@(?:augments|extends|class|interface|memberof!?|this)\s+)[A-Z]\w*(?:\.[A-Z]\w*)*/,lookbehind:!0,inside:{punctuation:/\./}}],example:{pattern:/(@example\s+)[^@]+?(?=\s*(?:\*\s*)?(?:@\w|\*\/))/,lookbehind:!0,inside:{code:{pattern:/^(\s*(?:\*\s*)?).+$/m,lookbehind:!0,inside:t,alias:"language-javascript"}}}}),e.languages.javadoclike.addSupport("javascript",e.languages.jsdoc)}(a),a.languages.actionscript=a.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|else|extends|finally|for|function|if|implements|import|in|instanceof|interface|internal|is|native|new|null|package|private|protected|public|return|super|switch|this|throw|try|typeof|use|var|void|while|with|dynamic|each|final|get|include|namespace|native|override|set|static)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<>?>?|[!=]=?)=?|[~?@]/}),a.languages.actionscript["class-name"].alias="function",a.languages.markup&&a.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:{rest:a.languages.markup}}}),function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},rest:e.languages.javascript}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(a),function(e){e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:(?:Uint|Int)(?:8|16|32)|Uint8Clamped|Float(?:32|64))?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|(?:Weak)?(?:Set|Map)|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:/(\.\s*)#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*/,lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|location|navigator|performance|(?:local|session)Storage|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var t=["function","function-variable","method","method-variable","property-access"],n=0;n))/i,delete e.languages.flow.parameter,e.languages.insertBefore("flow","operator",{"flow-punctuation":{pattern:/\{\||\|\}/,alias:"punctuation"}}),Array.isArray(e.languages.flow.keyword)||(e.languages.flow.keyword=[e.languages.flow.keyword]),e.languages.flow.keyword.unshift({pattern:/(^|[^$]\b)(?:type|opaque|declare|Class)\b(?!\$)/,lookbehind:!0},{pattern:/(^|[^$]\B)\$(?:await|Diff|Exact|Keys|ObjMap|PropertyType|Shape|Record|Supertype|Subtype|Enum)\b(?!\$)/,lookbehind:!0})}(a),a.languages.n4js=a.languages.extend("javascript",{keyword:/\b(?:any|Array|boolean|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|module|new|null|number|package|private|protected|public|return|set|static|string|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/}),a.languages.insertBefore("n4js","constant",{annotation:{pattern:/@+\w+/,alias:"operator"}}),a.languages.n4jsd=a.languages.n4js,a.languages.typescript=a.languages.extend("javascript",{keyword:/\b(?:abstract|as|async|await|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|is|keyof|let|module|namespace|new|null|of|package|private|protected|public|readonly|return|require|set|static|super|switch|this|throw|try|type|typeof|var|void|while|with|yield)\b/,builtin:/\b(?:string|Function|any|number|boolean|Array|symbol|console|Promise|unknown|never)\b/}),a.languages.ts=a.languages.typescript,function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,o=r.inside["interpolation-punctuation"],i=r.pattern.source;function a(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function l(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function u(t,n,r){var o={code:t,grammar:n,language:r};return e.hooks.run("before-tokenize",o),o.tokens=e.tokenize(o.code,o.grammar),e.hooks.run("after-tokenize",o),o.tokens}function s(t){var n={};n["interpolation-punctuation"]=o;var i=e.tokenize(t,n);if(3===i.length){var a=[1,1];a.push.apply(a,u(i[1],e.languages.javascript,"javascript")),i.splice.apply(i,a)}return new e.Token("interpolation",i,r.alias,t)}function c(t,n,r){var o=e.tokenize(t,{interpolation:{pattern:RegExp(i),lookbehind:!0}}),a=0,c={},d=u(o.map((function(e){if("string"==typeof e)return e;for(var n,o=e.content;-1!==t.indexOf(n=l(a++,r)););return c[n]=o,n})).join(""),n,r),f=Object.keys(c);return a=0,function e(t){for(var n=0;n=f.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var o=f[a],i="string"==typeof r?r:r.content,l=i.indexOf(o);if(-1!==l){++a;var u=i.substring(0,l),d=s(c[o]),p=i.substring(l+o.length),m=[];if(u&&m.push(u),m.push(d),p){var h=[p];e(h),m.push.apply(m,h)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(m)),n+=m.length-1):r.content=m}}else{var g=r.content;Array.isArray(g)?e(g):e([g])}}}(d),new e.Token(r,d,"language-"+r,t)}e.languages.javascript["template-string"]=[a("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),a("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),a("svg",/\bsvg/.source),a("markdown",/\b(?:md|markdown)/.source),a("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),t].filter(Boolean);var d={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function f(e){return"string"==typeof e?e:Array.isArray(e)?e.map(f).join(""):f(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in d&&function t(n){for(var r=0,o=n.length;r/g,t),n&&(e=e+"|"+e.replace(/_/g,"\\*")),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``.+?``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,o=/\|?__(?:\|__)+\|?(?:(?:\r?\n|\r)|$)/.source.replace(/__/g,r),i=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\r?\n|\r)/.source;e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+o+i+"(?:"+o+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+o+i+")(?:"+o+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+o+")"+i+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+o+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/(^[ \t]*(?:\r?\n|\r))(?: {4}|\t).+(?:(?:\r?\n|\r)(?: {4}|\t).+)*/m,lookbehind:!0,alias:"keyword"},{pattern:/``.+?``|`[^`\r\n]+`/,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\r?\n|\r))[\s\S]+?(?=(?:\r?\n|\r)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\r?\n|\r)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/__(?:(?!_)|_(?:(?!_))+_)+__/.source,!0),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/_(?:(?!_)|__(?:(?!_))+__)+_/.source,!0),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~))+?\2/.source,!1),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},url:{pattern:n(/!?\[(?:(?!\]))+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[(?:(?!\]))+\])/.source,!1),lookbehind:!0,greedy:!0,inside:{variable:{pattern:/(\[)[^\]]+(?=\]$)/,lookbehind:!0},content:{pattern:/(^!?\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n",unchanged:" ",diff:"!"};Object.keys(t).forEach((function(n){var r=t[n],o=[];/^\w+$/.test(n)||o.push(/\w+/.exec(n)[0]),"diff"===n&&o.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:o}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}(a),a.languages.git={comment:/^#.*/m,deleted:/^[-\u2013].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/m,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/m}},coord:/^@@.*@@$/m,commit_sha1:/^commit \w{40}$/m},a.languages.go=a.languages.extend("clike",{keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,builtin:/\b(?:bool|byte|complex(?:64|128)|error|float(?:32|64)|rune|string|u?int(?:8|16|32|64)?|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(?:ln)?|real|recover)\b/,boolean:/\b(?:_|iota|nil|true|false)\b/,operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,number:/(?:\b0x[a-f\d]+|(?:\b\d+\.?\d*|\B\.\d+)(?:e[-+]?\d+)?)i?/i,string:{pattern:/(["'`])(\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0}}),delete a.languages.go["class-name"],function(e){e.languages.handlebars={comment:/\{\{![\s\S]*?\}\}/,delimiter:{pattern:/^\{\{\{?|\}\}\}?$/i,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,boolean:/\b(?:true|false)\b/,block:{pattern:/^(\s*~?\s*)[#\/]\S+?(?=\s*~?\s*$|\s)/i,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",(function(t){e.languages["markup-templating"].buildPlaceholders(t,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"handlebars")}))}(a),a.languages.json={property:{pattern:/"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,greedy:!0},string:{pattern:/"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,greedy:!0},comment:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,number:/-?\d+\.?\d*(e[+-]?\d+)?/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},a.languages.less=a.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-]+?(?:\([^{}]+\)|[^(){};])*?(?=\s*\{)/i,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\([^{}]*\)|[^{};@])*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/i,operator:/[+\-*\/]/}),a.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-]+.*?(?=[(;])/,lookbehind:!0,alias:"function"}}),a.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},builtin:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,symbol:{pattern:/^[^:=\r\n]+(?=\s*:(?!=))/m,inside:{variable:/\$+(?:[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:[/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,{pattern:/(\()(?:addsuffix|abspath|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:s|list)?)(?=[ \t])/,lookbehind:!0}],operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/},a.languages.objectivec=a.languages.extend("c",{keyword:/\b(?:asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while|in|self|super)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,string:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|@"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,operator:/-[->]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete a.languages.objectivec["class-name"],a.languages.ocaml={comment:/\(\*[\s\S]*?\*\)/,string:[{pattern:/"(?:\\.|[^\\\r\n"])*"/,greedy:!0},{pattern:/(['`])(?:\\(?:\d+|x[\da-f]+|.)|(?!\1)[^\\\r\n])\1/i,greedy:!0}],number:/\b(?:0x[\da-f][\da-f_]+|(?:0[bo])?\d[\d_]*\.?[\d_]*(?:e[+-]?[\d_]+)?)/i,type:{pattern:/\B['`]\w*/,alias:"variable"},directive:{pattern:/\B#\w+/,alias:"function"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|object|of|open|prefix|private|rec|then|sig|struct|to|try|type|val|value|virtual|where|while|with)\b/,boolean:/\b(?:false|true)\b/,operator:/:=|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lxor|lsl|lsr|mod|nor|or)\b/,punctuation:/[(){}\[\]|_.,:;]/},a.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},"string-interpolation":{pattern:/(?:f|rf|fr)(?:("""|''')[\s\S]+?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|rb|br)?("""|''')[\s\S]+?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^\s*)@\w+(?:\.\w+)*/i,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:True|False|None)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},a.languages.python["string-interpolation"].inside.interpolation.inside.rest=a.languages.python,a.languages.py=a.languages.python,a.languages.reason=a.languages.extend("clike",{comment:{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:mod|land|lor|lxor|lsl|lsr|asr)\b/}),a.languages.insertBefore("reason","class-name",{character:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,alias:"string"},constructor:{pattern:/\b[A-Z]\w*\b(?!\s*\.)/,alias:"variable"},label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete a.languages.reason.function,function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t]+.+)*/m,lookbehind:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,inside:{atrule:/(?:@[\w-]+|[+=])/m}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|or|not)\b/,{pattern:/(\s+)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s]+.*)/m,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/([ \t]*)\S(?:,?[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,?[^,\r\n]+)*)*/,lookbehind:!0}})}(a),a.languages.scss=a.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-]+(?:\([^()]+\)|[^(])*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()]|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}]+[:{][^}]+))/m,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[\w-]|\$[-\w]+|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),a.languages.insertBefore("scss","atrule",{keyword:[/@(?:if|else(?: if)?|for|each|while|import|extend|debug|warn|mixin|include|function|return|content)/i,{pattern:/( +)(?:from|through)(?= )/,lookbehind:!0}]}),a.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),a.languages.insertBefore("scss","function",{placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|or|not)(?=\s)/,lookbehind:!0}}),a.languages.scss.atrule.inside.rest=a.languages.scss,a.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:TRUE|FALSE|NULL)\b/i,number:/\b0x[\da-f]+\b|\b\d+\.?\d*|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t={url:/url\((["']?).*?\1\)/i,string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:if|else|for|return|unless)(?=\s+|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,number:/\b\d+(?:\.\d+)?%?/,boolean:/\b(?:true|false)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.+|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],punctuation:/[{}()\[\];:,]/};t.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^{|}$/,alias:"punctuation"},rest:t}},t.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:t}},e.languages.stylus={comment:{pattern:/(^|[^\\])(\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},"atrule-declaration":{pattern:/(^\s*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:t}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:(?:\{[^}]*\}|.+)|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:t}},statement:{pattern:/(^[ \t]*)(?:if|else|for|return|unless)[ \t]+.+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:t}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)[^{\r\n]*(?:;|[^{\r\n,](?=$)(?!(\r?\n|\r)(?:\{|\2[ \t]+)))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:t.interpolation}},rest:t}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\))?|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\))?|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t]+)))/m,lookbehind:!0,inside:{interpolation:t.interpolation,punctuation:/[{},]/}},func:t.func,string:t.string,interpolation:t.interpolation,punctuation:/[{}()\[\];:.]/}}(a);var l=a.util.clone(a.languages.typescript);a.languages.tsx=a.languages.extend("jsx",l),a.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|nearest|neg?|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|store(?:8|16|32)?|sqrt|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^_`|~]+/i,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/},a.languages.yaml={scalar:{pattern:/([\-:]\s*(?:![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\2[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(?:![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?)(?=[ \t]*(?:$|,|]|}))/m,lookbehind:!0,alias:"number"},boolean:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},null:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)("|')(?:(?!\2)[^\\\r\n]|\\.)*\2(?=[ \t]*(?:$|,|]|}|\s*#))/m,lookbehind:!0,greedy:!0},number:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+\.?\d*|\.?\d+)(?:e[+-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},a.languages.yml=a.languages.yaml,t.a=a},function(e,t,n){"use strict";var r=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;function a(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(o){return!1}}()?Object.assign:function(e,t){for(var n,l,u=a(e),s=1;s0?r:n)(e)}},function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t,n){var r=n(24).f,o=n(14),i=n(11)("toStringTag");e.exports=function(e,t,n){e&&!o(e=n?e:e.prototype,i)&&r(e,i,{configurable:!0,value:t})}},function(e,t,n){"use strict";var r=n(10);t.a=r.b},function(e,t,n){"use strict";e.exports=n(83)},function(e,t,n){"use strict";var r=n(0),o=n.n(r);t.a=o.a.createContext({})},,function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE){0;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}}(),e.exports=n(55)},function(e,t,n){"use strict";var r=n(47),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},i={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},a={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},l={};function u(e){return r.isMemo(e)?a:l[e.$$typeof]||o}l[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},l[r.Memo]=a;var s=Object.defineProperty,c=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var o=p(n);o&&o!==m&&e(t,o,r)}var a=c(n);d&&(a=a.concat(d(n)));for(var l=u(t),h=u(n),g=0;gA.length&&A.push(e)}function I(e,t,n){return null==e?0:function e(t,n,r,o){var l=typeof t;"undefined"!==l&&"boolean"!==l||(t=null);var u=!1;if(null===t)u=!0;else switch(l){case"string":case"number":u=!0;break;case"object":switch(t.$$typeof){case i:case a:u=!0}}if(u)return r(o,t,""===n?"."+L(t,0):n),1;if(u=0,n=""===n?".":n+":",Array.isArray(t))for(var s=0;s