/* Copyright 2015 The Kubernetes Authors All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // generated by hack/build-ui.sh; DO NOT EDIT package ui import ( "fmt" "io/ioutil" "os" "path" "path/filepath" "strings" "time" ) type asset struct { bytes []byte info os.FileInfo } type bindata_file_info struct { name string size int64 mode os.FileMode modTime time.Time } func (fi bindata_file_info) Name() string { return fi.name } func (fi bindata_file_info) Size() int64 { return fi.size } func (fi bindata_file_info) Mode() os.FileMode { return fi.mode } func (fi bindata_file_info) ModTime() time.Time { return fi.modTime } func (fi bindata_file_info) IsDir() bool { return false } func (fi bindata_file_info) Sys() interface{} { return nil } var _www_app_assets_css_app_css = []byte(`.nav-back { width: 80px; font-size: 14px; padding-left: 14px; line-height: 15px; } .nav-back { /* :before */ /* content: ""; */ background-size: 14px 14px; background-repeat: no-repeat; display: block; } a { text-decoration: none; } .main-fab { position: absolute; z-index: 20; font-size: 30px; top: 100px; left: 24px; transform: scale(0.88, 0.88); } .md-breadcrumb { padding-left: 16px; } .md-table { min-width: 100%; border-collapse: collapse; } .md-table tbody tr:hover, .md-table tbody tr:focus { cursor: pointer; background-color: rgba(63, 81, 181, 0.2); } .md-table-header { border-bottom: 1px solid #e6e6e6; color: #828282; text-align: left; font-size: 0.75em; font-weight: 700; padding: 16px 16px 16px 0; } .md-table-header a { text-decoration: none; color: inherit; } .md-table-caret { display: inline-block; vertical-align: middle; } .md-table-content { font-size: 0.8em; padding: 16px 16px 16px 0; height: 72px; } .md-table-td-more { max-width: 72px; width: 72px; padding: 16px; } .md-table-thumbs { max-width: 104px; width: 104px; padding: 16px 32px; } .md-table-thumbs div { overflow: hidden; width: 40px; height: 40px; border-radius: 20px; border: 1px solid rgba(0, 0, 0, 0.2); background-size: cover; box-shadow: 0 8px 10px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 8px 10px rgba(0, 0, 0, 0.1); } .md-table-footer { height: 40px; } .md-table-count-info { line-height: 40px; font-size: .75em; } .md-table-footer-item { width: 40px; height: 40px; vertical-align: middle; } .md-table-active-page { font-weight: 700; } .bold { font-weight: 700; } .grey, .gray { color: #888888; } md-input-container.md-default-theme .md-input { color: white; border-color: white; margin-top: 24px; } .dashboard-subnav { font-size: 0.9em; min-height: 38px; max-height: 38px; background-color: #09c1d1 !important; } .dashboard-subnav md-select.md-default-theme:focus .md-select-label { border-bottom: none; color: white; } .selectSubPages p { text-align: center; color: #fff; } .selectSubPages .md-default-theme .md-select-label.md-placeholder { color: #fff; } .selectSubPages .md-select-label { padding-top: 0px; font-size: 1em; line-height: 1em; border-bottom: none; padding-bottom: 0px; } .selectSubPages md-select { margin-top: 10px; margin-right: 80px; padding: 0px; } md-select-menu { max-height: none; } .md-toolbar-tools { padding-left: 8px; padding-right: 8px; } .md-toolbar-small { height: 38px; min-height: 38px; } .md-toolbar-tools-small { background-color: #09c1d1; } /* Begin kubernetes-ui Menu */ .kubernetes-ui-menu, .kubernetes-ui-menu ul { list-style: none; padding: 0; } .kubernetes-ui-menu li { margin: 0; } .kubernetes-ui-menu > li { border-top: 1px solid rgba(0, 0, 0, 0.12); } .kubernetes-ui-menu .md-button { border-radius: 0; color: inherit; cursor: pointer; font-weight: 400; line-height: 40px; margin: 0; max-height: 40px; overflow: hidden; padding: 0px 16px; text-align: left; text-decoration: none; white-space: normal; width: 100%; } .kubernetes-ui-menu a.md-button { display: block; } .kubernetes-ui-menu button.md-button::-moz-focus-inner { padding: 0; } .kubernetes-ui-menu .md-button.active { color: #03a9f4; } .menu-heading { color: #888; display: block; font-size: inherit; font-weight: 500; line-height: 40px; margin: 0; padding: 0px 16px; text-align: left; width: 100%; } .kubernetes-ui-menu li.parentActive, .kubernetes-ui-menu li.parentActive .menu-toggle-list { background-color: #f6f6f6; } .menu-toggle-list { background: #fff; max-height: 999px; overflow: hidden; position: relative; z-index: 1; -webkit-transition: 0.75s cubic-bezier(0.35, 0, 0.25, 1); -webkit-transition-property: max-height; -moz-transition: 0.75s cubic-bezier(0.35, 0, 0.25, 1); -moz-transition-property: max-height; transition: 0.75s cubic-bezier(0.35, 0, 0.25, 1); transition-property: max-height; } .menu-toggle-list.ng-hide { max-height: 0; } .kubernetes-ui-menu .menu-toggle-list a.md-button { display: block; padding: 0 16px 0 32px; text-transform: none; } .md-button-toggle .md-toggle-icon { background: transparent url(../img/icons/list_control_down.png) no-repeat center center; background-size: 100% auto; display: inline-block; height: 24px; margin: auto 0 auto auto; speak: none; width: 24px; transition: transform 0.3s ease-in-out; -webkit-transition: -webkit-transform 0.3s ease-in-out; } .md-button-toggle .md-toggle-icon.toggled { transform: rotate(180deg); -webkit-transform: rotate(180deg); } /* End kubernetes-ui Menu */ .menu-icon { background: none; border: none; margin-right: 16px; padding: 0; } .whiteframedemoBasicUsage md-whiteframe { background: #fff; margin: 2px; padding: 2px; } .tabsDefaultTabs { height: 100%; width: 100%; /* * Animation styles */ } .tabsDefaultTabs .remove-tab { margin-bottom: 40px; } .tabsDefaultTabs .home-buttons .md-button { display: block; max-height: 30px; } .tabsDefaultTabs .home-buttons .md-button.add-tab { margin-top: 20px; max-height: 30px !important; } .tabsDefaultTabs .demo-tab { display: block; position: relative; background: white; border: 0px solid black; min-height: 0px; width: 100%; } .tabsDefaultTabs .tab0, .tabsDefaultTabs .tab1, .tabsDefaultTabs .tab2, .tabsDefaultTabs .tab3 { background-color: #bbdefb; } .tabsDefaultTabs .md-header { background-color: #1976D2 !important; } .tabsDefaultTabs md-tab { color: #90caf9 !important; } .tabsDefaultTabs md-tab.active, .tabsDefaultTabs md-tab:focus { color: white !important; } .tabsDefaultTabs md-tab[disabled] { opacity: 0.5; } .tabsDefaultTabs .md-header .md-ripple { border-color: #FFFF8D !important; } .tabsDefaultTabs md-tabs-ink-bar { background-color: #FFFF8D !important; } .tabsDefaultTabs .title { padding-top: 8px; padding-right: 8px; text-align: left; text-transform: uppercase; color: #888; margin-top: 24px; } .tabsDefaultTabs [layout-align] > * { margin-left: 8px; } .tabsDefaultTabs form > [layout] > * { margin-left: 8px; } .tabsDefaultTabs .long > input { width: 264px; } .menuBtn { background-color: transparent; border: none; height: 38px; margin: 16px; position: absolute; width: 36px; } md-toolbar h1 { font-size: 1.250em; font-weight: 400; margin: auto; } md-list .md-button { color: inherit; font-weight: 500; text-align: left; width: 100%; } .visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } md-list .md-button { color: inherit; font-weight: 500; text-align: left; width: 100%; } md-list .md-button.selected { color: #03a9f4; } #content { overflow: hidden; } #content md-content { padding-left: 0px; padding-right: 0px; padding-top: 0px; } #content .md-button.action { background-color: transparent; border: none; height: 38px; margin: 8px auto 16px 0; position: absolute; top: 10px; right: 25px; width: 36px; } #content img { display: block; height: auto; max-width: 500px; } .content-wrapper { position: relative; } .visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } md-toolbar h1 { font-size: 1.250em; font-weight: 400; } .menuBtn { background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIyNHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPGcgaWQ9IkhlYWRlciI+CiAgICA8Zz4KICAgICAgICA8cmVjdCB4PSItNjE4IiB5PSItMjIzMiIgZmlsbD0ibm9uZSIgd2lkdGg9IjE0MDAiIGhlaWdodD0iMzYwMCIvPgogICAgPC9nPgo8L2c+CjxnIGlkPSJMYWJlbCI+CjwvZz4KPGcgaWQ9Ikljb24iPgogICAgPGc+CiAgICAgICAgPHJlY3QgZmlsbD0ibm9uZSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ii8+CiAgICAgICAgPHBhdGggZD0iTTMsMThoMTh2LTJIM1YxOHogTTMsMTNoMTh2LTJIM1YxM3ogTTMsNnYyaDE4VjZIM3oiIHN0eWxlPSJmaWxsOiNmM2YzZjM7Ii8+CiAgICA8L2c+CjwvZz4KPGcgaWQ9IkdyaWQiIGRpc3BsYXk9Im5vbmUiPgogICAgPGcgZGlzcGxheT0iaW5saW5lIj4KICAgIDwvZz4KPC9nPgo8L3N2Zz4=) no-repeat center center; } .actionBtn { background: url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzNiIgaGVpZ2h0PSIzNiIgdmlld0JveD0iMCAwIDM2IDM2Ij4NCiAgICA8cGF0aCBkPSJNMCAwaDM2djM2aC0zNnoiIGZpbGw9Im5vbmUiLz4NCiAgICA8cGF0aCBkPSJNNCAyN2gyOHYtM2gtMjh2M3ptMC04aDI4di0zaC0yOHYzem0wLTExdjNoMjh2LTNoLTI4eiIvPg0KPC9zdmc+) no-repeat center center; } .kubernetes-ui-logo { background-image: url("../img/kubernetes.svg"); background-size: 40px 40px; width: 40px; height: 40px; } .kubernetes-ui-text { line-height: 40px; vertical-align: middle; padding: 2px; } md-select-menu.md-default-theme md-option:focus:not([selected]) { background: #eeeeee; } md-select-menu md-option { transition: box-shadow 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), background-color 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), -webkit-transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); transition: box-shadow 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), background-color 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); } md-select-menu md-option:not([disabled]):hover, md-select-menu md-option:not([disabled]):focus { background-color: rgba(158, 158, 158, 0.2); } .dashboard .body-wrapper { padding: 25px; } .dashboard [flex-align-self="end"] { -webkit-align-self: flex-end; -ms-flex-align-self: end; align-self: flex-end; } .dashboard .back { font-size: 18px; line-height: 27px; margin-bottom: 30px; } .dashboard .heading { font-size: 18px; line-height: 21px; color: #222222; margin-bottom: 25px; } .dashboard .heading .label { color: #777777; } .dashboard .clear-bg { background-color: transparent; } .dashboard .list-pods .pod-group { margin: 25px; } .dashboard .list-pods .pod-group md-grid-list { margin-top: 50px; color: white; } .dashboard .list-pods .pod-group md-grid-list figcaption { width: 100%; } .dashboard .list-pods .pod-group md-grid-list md-grid-tile-header { padding-left: 10px; } .dashboard .list-pods .pod-group md-grid-list md-grid-tile-header .labels { width: 100%; } .dashboard .list-pods .pod-group md-grid-list md-grid-tile { transition: all 700ms ease-in 50ms; } .dashboard .list-pods .pod-group md-grid-list .inner-box { padding-left: 10px; padding-right: 10px; } .dashboard .list-pods .pod-group md-grid-list md-grid-tile-footer { background: rgba(0, 0, 0, 0.5); } .dashboard .list-pods .pod-group md-grid-list md-grid-tile-footer .pod-title { margin-left: 10px; } .dashboard .list-pods .pod-group md-grid-list md-grid-tile-footer .pod-host { text-align: right; padding-right: 15px; } .dashboard .list-pods .pod-group md-grid-list md-grid-tile-footer a { color: white; } .dashboard .list-pods .pod-group md-grid-list .restarts { width: 100%; text-align: right; padding-right: 10px; } .dashboard .list-pods .pod-group md-grid-list .restarts .restart-button, .dashboard .list-pods .pod-group md-grid-list .restarts .restart-button:not([disabled]):hover, .dashboard .list-pods .pod-group md-grid-list .restarts .restart-button:not([disabled]):focus, .dashboard .list-pods .pod-group md-grid-list .restarts .restart-button:hover, .dashboard .list-pods .pod-group md-grid-list .restarts .restart-button:focus { background-color: #ff1744; width: 30px; height: 30px; } .dashboard .list-pods .gray { background: #f5f5f5; } .dashboard .list-pods .dark-overlay { background-color: #292935; opacity: 0.5; } .dashboard .list-pods .light-overlay { background-color: #FFFFFF; opacity: 0.2; } .dashboard .list-pods .color-1 { background-color: #2962ff; fill: #2962ff; stroke: #2962ff; } .dashboard .list-pods md-grid-list.list-color-1 md-grid-tile.colored { background-color: #2962ff; } .dashboard .list-pods .color-2 { background-color: #aa00ff; fill: #aa00ff; stroke: #aa00ff; } .dashboard .list-pods md-grid-list.list-color-2 md-grid-tile.colored { background-color: #aa00ff; } .dashboard .list-pods .color-3 { background-color: #00c853; fill: #00c853; stroke: #00c853; } .dashboard .list-pods md-grid-list.list-color-3 md-grid-tile.colored { background-color: #00c853; } .dashboard .list-pods .color-4 { background-color: #304ffe; fill: #304ffe; stroke: #304ffe; } .dashboard .list-pods md-grid-list.list-color-4 md-grid-tile.colored { background-color: #304ffe; } .dashboard .list-pods .color-5 { background-color: #0091ea; fill: #0091ea; stroke: #0091ea; } .dashboard .list-pods md-grid-list.list-color-5 md-grid-tile.colored { background-color: #0091ea; } .dashboard .list-pods .color-6 { background-color: #ff6d00; fill: #ff6d00; stroke: #ff6d00; } .dashboard .list-pods md-grid-list.list-color-6 md-grid-tile.colored { background-color: #ff6d00; } .dashboard .list-pods .color-7 { background-color: #00bfa5; fill: #00bfa5; stroke: #00bfa5; } .dashboard .list-pods md-grid-list.list-color-7 md-grid-tile.colored { background-color: #00bfa5; } .dashboard .list-pods .color-8 { background-color: #c51162; fill: #c51162; stroke: #c51162; } .dashboard .list-pods md-grid-list.list-color-8 md-grid-tile.colored { background-color: #c51162; } .dashboard .list-pods .color-9 { background-color: #64dd17; fill: #64dd17; stroke: #64dd17; } .dashboard .list-pods md-grid-list.list-color-9 md-grid-tile.colored { background-color: #64dd17; } .dashboard .list-pods .color-10 { background-color: #6200ea; fill: #6200ea; stroke: #6200ea; } .dashboard .list-pods md-grid-list.list-color-10 md-grid-tile.colored { background-color: #6200ea; } .dashboard .list-pods .color-11 { background-color: #ffd600; fill: #ffd600; stroke: #ffd600; } .dashboard .list-pods md-grid-list.list-color-11 md-grid-tile.colored { background-color: #ffd600; } .dashboard .list-pods .color-12 { background-color: #00b8d4; fill: #00b8d4; stroke: #00b8d4; } .dashboard .list-pods md-grid-list.list-color-12 md-grid-tile.colored { background-color: #00b8d4; } .dashboard .list-pods .color-13 { background-color: #ffab00; fill: #ffab00; stroke: #ffab00; } .dashboard .list-pods md-grid-list.list-color-13 md-grid-tile.colored { background-color: #ffab00; } .dashboard .list-pods .color-14 { background-color: #dd2c00; fill: #dd2c00; stroke: #dd2c00; } .dashboard .list-pods md-grid-list.list-color-14 md-grid-tile.colored { background-color: #dd2c00; } .dashboard .list-pods .color-15 { background-color: #2979ff; fill: #2979ff; stroke: #2979ff; } .dashboard .list-pods md-grid-list.list-color-15 md-grid-tile.colored { background-color: #2979ff; } .dashboard .list-pods .color-16 { background-color: #d500f9; fill: #d500f9; stroke: #d500f9; } .dashboard .list-pods md-grid-list.list-color-16 md-grid-tile.colored { background-color: #d500f9; } .dashboard .list-pods .color-17 { background-color: #00e676; fill: #00e676; stroke: #00e676; } .dashboard .list-pods md-grid-list.list-color-17 md-grid-tile.colored { background-color: #00e676; } .dashboard .list-pods .color-18 { background-color: #3d5afe; fill: #3d5afe; stroke: #3d5afe; } .dashboard .list-pods md-grid-list.list-color-18 md-grid-tile.colored { background-color: #3d5afe; } .dashboard .list-pods .color-19 { background-color: #00b0ff; fill: #00b0ff; stroke: #00b0ff; } .dashboard .list-pods md-grid-list.list-color-19 md-grid-tile.colored { background-color: #00b0ff; } .dashboard .list-pods .color-20 { background-color: #ff9100; fill: #ff9100; stroke: #ff9100; } .dashboard .list-pods md-grid-list.list-color-20 md-grid-tile.colored { background-color: #ff9100; } .dashboard .list-pods .color-21 { background-color: #1de9b6; fill: #1de9b6; stroke: #1de9b6; } .dashboard .list-pods md-grid-list.list-color-21 md-grid-tile.colored { background-color: #1de9b6; } .dashboard .list-pods .color-22 { background-color: #f50057; fill: #f50057; stroke: #f50057; } .dashboard .list-pods md-grid-list.list-color-22 md-grid-tile.colored { background-color: #f50057; } .dashboard .list-pods .color-23 { background-color: #76ff03; fill: #76ff03; stroke: #76ff03; } .dashboard .list-pods md-grid-list.list-color-23 md-grid-tile.colored { background-color: #76ff03; } .dashboard .list-pods .color-24 { background-color: #651fff; fill: #651fff; stroke: #651fff; } .dashboard .list-pods md-grid-list.list-color-24 md-grid-tile.colored { background-color: #651fff; } .dashboard .list-pods .color-25 { background-color: #ffea00; fill: #ffea00; stroke: #ffea00; } .dashboard .list-pods md-grid-list.list-color-25 md-grid-tile.colored { background-color: #ffea00; } .dashboard .list-pods .color-26 { background-color: #00e5ff; fill: #00e5ff; stroke: #00e5ff; } .dashboard .list-pods md-grid-list.list-color-26 md-grid-tile.colored { background-color: #00e5ff; } .dashboard .list-pods .color-27 { background-color: #ffc400; fill: #ffc400; stroke: #ffc400; } .dashboard .list-pods md-grid-list.list-color-27 md-grid-tile.colored { background-color: #ffc400; } .dashboard .list-pods .color-28 { background-color: #ff3d00; fill: #ff3d00; stroke: #ff3d00; } .dashboard .list-pods md-grid-list.list-color-28 md-grid-tile.colored { background-color: #ff3d00; } .dashboard .list-pods .color-29 { background-color: #448aff; fill: #448aff; stroke: #448aff; } .dashboard .list-pods md-grid-list.list-color-29 md-grid-tile.colored { background-color: #448aff; } .dashboard .list-pods .color-30 { background-color: #e040fb; fill: #e040fb; stroke: #e040fb; } .dashboard .list-pods md-grid-list.list-color-30 md-grid-tile.colored { background-color: #e040fb; } .dashboard .list-pods .color-31 { background-color: #69f0ae; fill: #69f0ae; stroke: #69f0ae; } .dashboard .list-pods md-grid-list.list-color-31 md-grid-tile.colored { background-color: #69f0ae; } .dashboard .list-pods .color-32 { background-color: #536dfe; fill: #536dfe; stroke: #536dfe; } .dashboard .list-pods md-grid-list.list-color-32 md-grid-tile.colored { background-color: #536dfe; } .dashboard .list-pods .color-33 { background-color: #40c4ff; fill: #40c4ff; stroke: #40c4ff; } .dashboard .list-pods md-grid-list.list-color-33 md-grid-tile.colored { background-color: #40c4ff; } .dashboard .list-pods .color-34 { background-color: #ffab40; fill: #ffab40; stroke: #ffab40; } .dashboard .list-pods md-grid-list.list-color-34 md-grid-tile.colored { background-color: #ffab40; } .dashboard .list-pods .color-35 { background-color: #64ffda; fill: #64ffda; stroke: #64ffda; } .dashboard .list-pods md-grid-list.list-color-35 md-grid-tile.colored { background-color: #64ffda; } .dashboard .list-pods .color-36 { background-color: #ff4081; fill: #ff4081; stroke: #ff4081; } .dashboard .list-pods md-grid-list.list-color-36 md-grid-tile.colored { background-color: #ff4081; } .dashboard .list-pods .color-37 { background-color: #b2ff59; fill: #b2ff59; stroke: #b2ff59; } .dashboard .list-pods md-grid-list.list-color-37 md-grid-tile.colored { background-color: #b2ff59; } .dashboard .list-pods .color-38 { background-color: #7c4dff; fill: #7c4dff; stroke: #7c4dff; } .dashboard .list-pods md-grid-list.list-color-38 md-grid-tile.colored { background-color: #7c4dff; } .dashboard .list-pods .color-39 { background-color: #ffff00; fill: #ffff00; stroke: #ffff00; } .dashboard .list-pods md-grid-list.list-color-39 md-grid-tile.colored { background-color: #ffff00; } .dashboard .list-pods .color-40 { background-color: #18ffff; fill: #18ffff; stroke: #18ffff; } .dashboard .list-pods md-grid-list.list-color-40 md-grid-tile.colored { background-color: #18ffff; } .dashboard .list-pods .color-41 { background-color: #ffd740; fill: #ffd740; stroke: #ffd740; } .dashboard .list-pods md-grid-list.list-color-41 md-grid-tile.colored { background-color: #ffd740; } .dashboard .list-pods .color-42 { background-color: #ff6e40; fill: #ff6e40; stroke: #ff6e40; } .dashboard .list-pods md-grid-list.list-color-42 md-grid-tile.colored { background-color: #ff6e40; } .dashboard .list-pods .color-warning { background-color: #ff9800 !important; border-color: #ff9800 !important; fill: #ff9800 !important; stroke: #ff9800 !important; } .dashboard .list-pods .color-critical { background-color: #f44336 !important; border-color: #f44336 !important; fill: #f44336 !important; stroke: #f44336 !important; } .dashboard .list-pods .status-waiting { background-color: #2e2e3b !important; border-color: #dad462 !important; border-width: 2px !important; border-style: solid !important; } .dashboard .list-pods .status-terminated, .dashboard .list-pods .status-unknown { background-color: #ff1744 !important; border-color: #e3002c !important; border-width: 1px !important; border-style: solid !important; } .dashboard .dash-table { min-width: 100%; border-collapse: collapse; } .dashboard .dash-table tbody tr:hover:not(.no-link), .dashboard .dash-table tbody tr:focus:not(.no-link) { cursor: pointer; background-color: rgba(63, 81, 181, 0.2); } .dashboard .dash-table .dash-table-header { border-bottom: 1px solid #e6e6e6; color: #828282; text-align: left; font-size: 0.75em; font-weight: 700; padding: 16px 16px 16px 0; } .dashboard .dash-table .dash-table-header a { text-decoration: none; color: inherit; } .dashboard .dash-table .dash-table-caret { display: inline-block; vertical-align: middle; } .dashboard .dash-table .dash-table-content { font-size: 0.8em; padding: 16px 16px 16px 0; height: 72px; } .dashboard .dash-table .dash-table-td-more { max-width: 72px; width: 72px; padding: 16px; } .dashboard .dash-table .dash-table-thumbs { max-width: 104px; width: 104px; padding: 16px 32px; } .dashboard .dash-table .dash-table-thumbs div { overflow: hidden; width: 40px; height: 40px; border-radius: 20px; border: 1px solid rgba(0, 0, 0, 0.2); background-size: cover; box-shadow: 0 8px 10px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 8px 10px rgba(0, 0, 0, 0.1); } .dashboard .dash-table .dash-table-footer { height: 40px; } .dashboard .dash-table .dash-table-count-info { line-height: 40px; font-size: .75em; } .dashboard .dash-table .dash-table-footer-item { width: 40px; height: 40px; vertical-align: middle; } .dashboard .dash-table .dash-table-active-page { font-weight: 700; } .dashboard .dash-table .bold { font-weight: 700; } .dashboard .dash-table .grey { color: grey; } .dashboard .dash-table md-input-container.md-default-theme .md-input { color: white; border-color: white; margin-top: 24px; } .dashboard .server-overview .dark-overlay { background-color: #292935; opacity: 0.5; } .dashboard .server-overview .light-overlay { background-color: #FFFFFF; opacity: 0.2; } .dashboard .server-overview .color-1 { background-color: #2962ff; fill: #2962ff; stroke: #2962ff; } .dashboard .server-overview md-grid-list.list-color-1 md-grid-tile.colored { background-color: #2962ff; } .dashboard .server-overview .color-2 { background-color: #aa00ff; fill: #aa00ff; stroke: #aa00ff; } .dashboard .server-overview md-grid-list.list-color-2 md-grid-tile.colored { background-color: #aa00ff; } .dashboard .server-overview .color-3 { background-color: #00c853; fill: #00c853; stroke: #00c853; } .dashboard .server-overview md-grid-list.list-color-3 md-grid-tile.colored { background-color: #00c853; } .dashboard .server-overview .color-4 { background-color: #304ffe; fill: #304ffe; stroke: #304ffe; } .dashboard .server-overview md-grid-list.list-color-4 md-grid-tile.colored { background-color: #304ffe; } .dashboard .server-overview .color-5 { background-color: #0091ea; fill: #0091ea; stroke: #0091ea; } .dashboard .server-overview md-grid-list.list-color-5 md-grid-tile.colored { background-color: #0091ea; } .dashboard .server-overview .color-6 { background-color: #ff6d00; fill: #ff6d00; stroke: #ff6d00; } .dashboard .server-overview md-grid-list.list-color-6 md-grid-tile.colored { background-color: #ff6d00; } .dashboard .server-overview .color-7 { background-color: #00bfa5; fill: #00bfa5; stroke: #00bfa5; } .dashboard .server-overview md-grid-list.list-color-7 md-grid-tile.colored { background-color: #00bfa5; } .dashboard .server-overview .color-8 { background-color: #c51162; fill: #c51162; stroke: #c51162; } .dashboard .server-overview md-grid-list.list-color-8 md-grid-tile.colored { background-color: #c51162; } .dashboard .server-overview .color-9 { background-color: #64dd17; fill: #64dd17; stroke: #64dd17; } .dashboard .server-overview md-grid-list.list-color-9 md-grid-tile.colored { background-color: #64dd17; } .dashboard .server-overview .color-10 { background-color: #6200ea; fill: #6200ea; stroke: #6200ea; } .dashboard .server-overview md-grid-list.list-color-10 md-grid-tile.colored { background-color: #6200ea; } .dashboard .server-overview .color-11 { background-color: #ffd600; fill: #ffd600; stroke: #ffd600; } .dashboard .server-overview md-grid-list.list-color-11 md-grid-tile.colored { background-color: #ffd600; } .dashboard .server-overview .color-12 { background-color: #00b8d4; fill: #00b8d4; stroke: #00b8d4; } .dashboard .server-overview md-grid-list.list-color-12 md-grid-tile.colored { background-color: #00b8d4; } .dashboard .server-overview .color-13 { background-color: #ffab00; fill: #ffab00; stroke: #ffab00; } .dashboard .server-overview md-grid-list.list-color-13 md-grid-tile.colored { background-color: #ffab00; } .dashboard .server-overview .color-14 { background-color: #dd2c00; fill: #dd2c00; stroke: #dd2c00; } .dashboard .server-overview md-grid-list.list-color-14 md-grid-tile.colored { background-color: #dd2c00; } .dashboard .server-overview .color-15 { background-color: #2979ff; fill: #2979ff; stroke: #2979ff; } .dashboard .server-overview md-grid-list.list-color-15 md-grid-tile.colored { background-color: #2979ff; } .dashboard .server-overview .color-16 { background-color: #d500f9; fill: #d500f9; stroke: #d500f9; } .dashboard .server-overview md-grid-list.list-color-16 md-grid-tile.colored { background-color: #d500f9; } .dashboard .server-overview .color-17 { background-color: #00e676; fill: #00e676; stroke: #00e676; } .dashboard .server-overview md-grid-list.list-color-17 md-grid-tile.colored { background-color: #00e676; } .dashboard .server-overview .color-18 { background-color: #3d5afe; fill: #3d5afe; stroke: #3d5afe; } .dashboard .server-overview md-grid-list.list-color-18 md-grid-tile.colored { background-color: #3d5afe; } .dashboard .server-overview .color-19 { background-color: #00b0ff; fill: #00b0ff; stroke: #00b0ff; } .dashboard .server-overview md-grid-list.list-color-19 md-grid-tile.colored { background-color: #00b0ff; } .dashboard .server-overview .color-20 { background-color: #ff9100; fill: #ff9100; stroke: #ff9100; } .dashboard .server-overview md-grid-list.list-color-20 md-grid-tile.colored { background-color: #ff9100; } .dashboard .server-overview .color-21 { background-color: #1de9b6; fill: #1de9b6; stroke: #1de9b6; } .dashboard .server-overview md-grid-list.list-color-21 md-grid-tile.colored { background-color: #1de9b6; } .dashboard .server-overview .color-22 { background-color: #f50057; fill: #f50057; stroke: #f50057; } .dashboard .server-overview md-grid-list.list-color-22 md-grid-tile.colored { background-color: #f50057; } .dashboard .server-overview .color-23 { background-color: #76ff03; fill: #76ff03; stroke: #76ff03; } .dashboard .server-overview md-grid-list.list-color-23 md-grid-tile.colored { background-color: #76ff03; } .dashboard .server-overview .color-24 { background-color: #651fff; fill: #651fff; stroke: #651fff; } .dashboard .server-overview md-grid-list.list-color-24 md-grid-tile.colored { background-color: #651fff; } .dashboard .server-overview .color-25 { background-color: #ffea00; fill: #ffea00; stroke: #ffea00; } .dashboard .server-overview md-grid-list.list-color-25 md-grid-tile.colored { background-color: #ffea00; } .dashboard .server-overview .color-26 { background-color: #00e5ff; fill: #00e5ff; stroke: #00e5ff; } .dashboard .server-overview md-grid-list.list-color-26 md-grid-tile.colored { background-color: #00e5ff; } .dashboard .server-overview .color-27 { background-color: #ffc400; fill: #ffc400; stroke: #ffc400; } .dashboard .server-overview md-grid-list.list-color-27 md-grid-tile.colored { background-color: #ffc400; } .dashboard .server-overview .color-28 { background-color: #ff3d00; fill: #ff3d00; stroke: #ff3d00; } .dashboard .server-overview md-grid-list.list-color-28 md-grid-tile.colored { background-color: #ff3d00; } .dashboard .server-overview .color-29 { background-color: #448aff; fill: #448aff; stroke: #448aff; } .dashboard .server-overview md-grid-list.list-color-29 md-grid-tile.colored { background-color: #448aff; } .dashboard .server-overview .color-30 { background-color: #e040fb; fill: #e040fb; stroke: #e040fb; } .dashboard .server-overview md-grid-list.list-color-30 md-grid-tile.colored { background-color: #e040fb; } .dashboard .server-overview .color-31 { background-color: #69f0ae; fill: #69f0ae; stroke: #69f0ae; } .dashboard .server-overview md-grid-list.list-color-31 md-grid-tile.colored { background-color: #69f0ae; } .dashboard .server-overview .color-32 { background-color: #536dfe; fill: #536dfe; stroke: #536dfe; } .dashboard .server-overview md-grid-list.list-color-32 md-grid-tile.colored { background-color: #536dfe; } .dashboard .server-overview .color-33 { background-color: #40c4ff; fill: #40c4ff; stroke: #40c4ff; } .dashboard .server-overview md-grid-list.list-color-33 md-grid-tile.colored { background-color: #40c4ff; } .dashboard .server-overview .color-34 { background-color: #ffab40; fill: #ffab40; stroke: #ffab40; } .dashboard .server-overview md-grid-list.list-color-34 md-grid-tile.colored { background-color: #ffab40; } .dashboard .server-overview .color-35 { background-color: #64ffda; fill: #64ffda; stroke: #64ffda; } .dashboard .server-overview md-grid-list.list-color-35 md-grid-tile.colored { background-color: #64ffda; } .dashboard .server-overview .color-36 { background-color: #ff4081; fill: #ff4081; stroke: #ff4081; } .dashboard .server-overview md-grid-list.list-color-36 md-grid-tile.colored { background-color: #ff4081; } .dashboard .server-overview .color-37 { background-color: #b2ff59; fill: #b2ff59; stroke: #b2ff59; } .dashboard .server-overview md-grid-list.list-color-37 md-grid-tile.colored { background-color: #b2ff59; } .dashboard .server-overview .color-38 { background-color: #7c4dff; fill: #7c4dff; stroke: #7c4dff; } .dashboard .server-overview md-grid-list.list-color-38 md-grid-tile.colored { background-color: #7c4dff; } .dashboard .server-overview .color-39 { background-color: #ffff00; fill: #ffff00; stroke: #ffff00; } .dashboard .server-overview md-grid-list.list-color-39 md-grid-tile.colored { background-color: #ffff00; } .dashboard .server-overview .color-40 { background-color: #18ffff; fill: #18ffff; stroke: #18ffff; } .dashboard .server-overview md-grid-list.list-color-40 md-grid-tile.colored { background-color: #18ffff; } .dashboard .server-overview .color-41 { background-color: #ffd740; fill: #ffd740; stroke: #ffd740; } .dashboard .server-overview md-grid-list.list-color-41 md-grid-tile.colored { background-color: #ffd740; } .dashboard .server-overview .color-42 { background-color: #ff6e40; fill: #ff6e40; stroke: #ff6e40; } .dashboard .server-overview md-grid-list.list-color-42 md-grid-tile.colored { background-color: #ff6e40; } .dashboard .server-overview .color-warning { background-color: #ff9800 !important; border-color: #ff9800 !important; fill: #ff9800 !important; stroke: #ff9800 !important; } .dashboard .server-overview .color-critical { background-color: #f44336 !important; border-color: #f44336 !important; fill: #f44336 !important; stroke: #f44336 !important; } .dashboard .server-overview .status-waiting { background-color: #2e2e3b !important; border-color: #dad462 !important; border-width: 2px !important; border-style: solid !important; } .dashboard .server-overview .status-terminated, .dashboard .server-overview .status-unknown { background-color: #ff1744 !important; border-color: #e3002c !important; border-width: 1px !important; border-style: solid !important; } .dashboard .server-overview .color-1 { background-color: #512DA8; border-color: #512DA8; fill: #512DA8; stroke: #512DA8; } .dashboard .server-overview .color-2 { background-color: #9C27B0; border-color: #9C27B0; fill: #9C27B0; stroke: #9C27B0; } .dashboard .server-overview .color-3 { background-color: #00BCD4; border-color: #00BCD4; fill: #00BCD4; stroke: #00BCD4; } .dashboard .server-overview .color-max-1 { background-color: #c5b6eb; border-color: #c5b6eb; fill: #c5b6eb; } .dashboard .server-overview .color-max-2 { background-color: #e6b5ee; border-color: #e6b5ee; fill: #e6b5ee; } .dashboard .server-overview .color-max-3 { background-color: #a1f4ff; border-color: #a1f4ff; fill: #a1f4ff; } .dashboard .server-overview .color-max-warning { background-color: #ffd699 !important; border-color: #ffd699 !important; fill: #ffd699 !important; } .dashboard .server-overview .color-max-critical { background-color: #fccbc7 !important; border-color: #fccbc7 !important; fill: #fccbc7 !important; } .dashboard .server-overview .max_tick_arc { stroke: #FFF !important; } .dashboard .server-overview .concentricchart .bg-circle { background: #F9F9F9; fill: #F9F9F9; stroke: #FFFFFF; stroke-width: 1px; } .dashboard .server-overview .concentricchart text { font-size: 12px; font-family: 'Roboto', sans-serif; } .dashboard .server-overview .concentricchart .value_group { fill: white; } .dashboard .server-overview .concentricchart .legend_group rect { opacity: 0.8; } .dashboard .server-overview svg.legend { height: 115px; } .dashboard .server-overview svg.legend text { font-size: 12px; font-family: 'Roboto', sans-serif; } .dashboard .server-overview svg.legend .hostName { font-size: 16px; } .dashboard .server-overview .minion-name { text-align: center; vertical-align: bottom; width: 100%; } .dashboard .server-overview .chart_area { width: 325px; height: 425px; } .dashboard .groups { font-size: 13px; } .dashboard .groups .header { line-height: 21px; } .dashboard .groups .header a { padding-left: 5px; padding-right: 5px; } .dashboard .groups .header .selector-area .filter-text { font-size: 13px; margin-left: 10px; } .dashboard .groups .header .selector-area .cancel-button { width: 18px; height: 18px; padding: 0; } .dashboard .groups .header .selector-area .cancel-button:focus, .dashboard .groups .header .selector-area .cancel-button:hover { background-color: none !important; } .dashboard .groups .header .selector-area .cancel-icon { width: 15px; height: 15px; fill: #777777; } .dashboard .groups .select-group-by { min-width: 110px; margin-left: 10px; margin-right: 40px; } .dashboard .groups .select-group-by .md-select-label { padding-top: 6px; font-size: 13px; } .dashboard .groups .group-item { padding-top: 20px; } .dashboard .groups .group-item .filter-button { height: 18px; width: 18px; } .dashboard .groups .group-item .filter-button .filter-icon { width: 18px; height: 18px; } .dashboard .groups .icon-area { min-width: 34px; } .dashboard .groups .icon-area .group-icon { border-radius: 21px; width: 21px; height: 21px; } .dashboard .groups .group-main-area .subtype { line-height: 21px; } .dashboard .groups md-divider { margin-top: 40px; margin-bottom: 30px; } .dashboard .groups .group-name { padding-top: 10px; } .dashboard .groups .selectFilter { padding-top: 10px; margin-right: 30px; } .dashboard .groups .selectFilter .md-select-label { border-bottom: none !important; width: 17px; min-width: 17px; padding-right: 0; } .dashboard .groups md-select-menu { min-height: 40px; max-height: 40px; } .dashboard .groups .group-link-area { padding-left: 15px; padding-bottom: 15px; } .dashboard .groups .group-link-area button { line-height: 12px; } .dashboard .groups .group-type-circle { width: 21px; height: 21px; } .dashboard .groups md-select { margin-top: 0px; } .dashboard .detail { color: #222222; } .dashboard .detail .back { font-size: 18px; line-height: 27px; margin-bottom: 30px; } .dashboard .detail .heading { font-size: 18px; line-height: 21px; color: #222222; margin-bottom: 25px; } .dashboard .detail .heading .label { color: #777777; } .dashboard .detail td.name { font-size: 14px; color: #222222; line-height: 24px; } .dashboard .detail td.value { margin-left: 50px; font-size: 14px; color: #888888; line-height: 24px; } .dashboard .detail .containerTable td { padding-right: 20px; } .dashboard .align-top tbody { vertical-align: top; } `) func www_app_assets_css_app_css_bytes() ([]byte, error) { return _www_app_assets_css_app_css, nil } func www_app_assets_css_app_css() (*asset, error) { bytes, err := www_app_assets_css_app_css_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/css/app.css", size: 37661, mode: os.FileMode(420), modTime: time.Unix(1432768981, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_docarrow_png = []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00!\x00\x00\x00\"\b\x06\x00\x00\x00\xd1p\xb0\xc1\x00\x00\x00\x04sBIT\b\b\b\b|\bd\x88\x00\x00\x00\tpHYs\x00\x00\x15\xfd\x00\x00\x15\xfd\x01\xcdpQa\x00\x00\x00\x1ctEXtSoftware\x00Adobe Fireworks CS6\u8f32\x8c\x00\x00\x00\xefIDATX\x85\xd5\xd71\x0e\xc20\f\x05\u0406\xebq\x0568\x01\x8c\x1c\x80\xeep\x1aV\x18Y`\x05\xc1\x19\x10e\x81\xe13\x05UU\xab\xd8\xf1\xb7\xa2~\xc9K\x87\xf4)\x8e\xea4\x00\xa8JgR\x1aPUcB\x84\x10\xfeU\xef.X\xac\x8eh?KU2\x00\x92\x15\xb3\u065e\x01\x00\xaf\xe6\x83\xf9\xf2 >L\xc9\xf5\xa5\x88\b\x88\xd1@(\x88u}B_\xa4\x10\nb:\xdb\xe3\xf6xfCh\xed\xb0@h\b\v\x84\x8a\u0205\xd0\x119\x10\x17\x84\x16\xe2\x86\xd0@\\\x11R\x88;\x82\x01\xa1 \xac\x10\xea(\x1f\xf2&')\xab\x1d\xd7{\xff.4\xef\xaf\u007f;\xac\x003B\x02\x90\xec\xb6\xe9c%\x01\xb8!4\x00\x17\x84\x16@G\xe4\x00\xa8\x88\\\x00\ra\x01\xd0\x10C\x17]\t\x80\u068e\xee\x95_\n\xa0\"\xda\x10\r\x80\x8e\x88\x10\r@\x82\b\u0757\x94\xc8x\xfe\u02bd\xf3\x03\xba\v\x18\x94\x12\x8b\x872\x00\x00\x00\x00IEND\xaeB`\x82") func www_app_assets_img_docarrow_png_bytes() ([]byte, error) { return _www_app_assets_img_docarrow_png, nil } func www_app_assets_img_docarrow_png() (*asset, error) { bytes, err := www_app_assets_img_docarrow_png_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/docArrow.png", size: 373, mode: os.FileMode(420), modTime: time.Unix(1429751137, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_ic_arrow_drop_down_24px_svg = []byte(` `) func www_app_assets_img_ic_arrow_drop_down_24px_svg_bytes() ([]byte, error) { return _www_app_assets_img_ic_arrow_drop_down_24px_svg, nil } func www_app_assets_img_ic_arrow_drop_down_24px_svg() (*asset, error) { bytes, err := www_app_assets_img_ic_arrow_drop_down_24px_svg_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/ic_arrow_drop_down_24px.svg", size: 166, mode: os.FileMode(420), modTime: time.Unix(1432748239, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_ic_arrow_drop_up_24px_svg = []byte(` `) func www_app_assets_img_ic_arrow_drop_up_24px_svg_bytes() ([]byte, error) { return _www_app_assets_img_ic_arrow_drop_up_24px_svg, nil } func www_app_assets_img_ic_arrow_drop_up_24px_svg() (*asset, error) { bytes, err := www_app_assets_img_ic_arrow_drop_up_24px_svg_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/ic_arrow_drop_up_24px.svg", size: 795, mode: os.FileMode(420), modTime: time.Unix(1432748239, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_ic_keyboard_arrow_left_24px_svg = []byte(``) func www_app_assets_img_ic_keyboard_arrow_left_24px_svg_bytes() ([]byte, error) { return _www_app_assets_img_ic_keyboard_arrow_left_24px_svg, nil } func www_app_assets_img_ic_keyboard_arrow_left_24px_svg() (*asset, error) { bytes, err := www_app_assets_img_ic_keyboard_arrow_left_24px_svg_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/ic_keyboard_arrow_left_24px.svg", size: 151, mode: os.FileMode(420), modTime: time.Unix(1432748239, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_ic_keyboard_arrow_right_24px_svg = []byte(``) func www_app_assets_img_ic_keyboard_arrow_right_24px_svg_bytes() ([]byte, error) { return _www_app_assets_img_ic_keyboard_arrow_right_24px_svg, nil } func www_app_assets_img_ic_keyboard_arrow_right_24px_svg() (*asset, error) { bytes, err := www_app_assets_img_ic_keyboard_arrow_right_24px_svg_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/ic_keyboard_arrow_right_24px.svg", size: 149, mode: os.FileMode(420), modTime: time.Unix(1432748239, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_icons_arrow_back_png = []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x80\x00\x00\x00\x80\b\x06\x00\x00\x00\xc3>a\xcb\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x020IDATx\x9c\xed\xddIn\x13q\x10F\xf1\u05c4\x05\xd7\xe0f\t\xc3\x166\x1c\xc0\x10\xa60\xc5!\x90\x046\x84Ab\xba\v7r`aY2\x02B\xecj\xf7_\xd5\xf5~\x92\x97\x91Jz_za\xc96H\x92$I\x92$I\x92$I\x92$I\x92$I\x92\xa4\xac\xb6Z\x1f\x90\xdc\x1ep\x15\xf8\xd1\xfa\x10\r\xab\x03\xde\x00?\x813\xe0V\xdbs4\xa4\xe5\xf8\x8b\x97#(\xa2\x03N\xf8=\xbe#(\xa2\x03\xa6\xfc=\xfe\xf2\bn\xb7:P\x9bs\x91\xf8\x8e`\xa4V\x89\xef\bF\xa6\x03\xf6Y-\xbe#\x18\x91\x87\xac\x17\u007f\xf1:\x1a\xfed\xf5e\xdd\xff\xfc\xc5k\xca\xfc\t\xa2\x84\xa2\xf1\x0f0~Z\xc6/,\x1a\xff%\xc6O\xeb\x05\xc6/+\x1a\xff\x10\xe3\xa7e\xfc\u008c_\xd8sb\xf1_a\xfc\xb4\x8c_X4\xfek\x8c\x9f\x96\xf1\v3~a\u03c8\xc5?\xc2\xf8i\x19\xbf0\xe3\x17\x16\x8d\u007f\x8c\xf1\xd3z\x8a\xf1\u02ca\xc6?\xc1\xf8iE\xe3\x9f\x02\x97\x86>Z\xfd0~aO0~Y\xd1\xf8\xef1~Z}\xc4\xf7;\x12\x922~a{\xc4\xe2\u007f\xc0\xf8i\x19\xbf\xb0h\xfc\x8f\x18?-\xe3\x17\xf6\x18\xe3\x975!\x16\xff\x13\xc6\xff\xa7\fo\x80\\\t\xfe\xfd\x8c\xf9\x10\x94\u0604\xd8S\xe0;py\xe8\xa3\u056f\t\x8e\xa0\xbc\t\xb1\x11|\xc3\x11\xa4w\x17GP\x9e#\x90#\x90#\x10p\x0fGP^t\x04_q\x04\xe99\x029\x02\xc1.\x8e\xa0\x8e\xa0x\xabsDG\xf0\x0eG\x90Z\xc7\xfc\xeb\xe2##\xf0\xe7\xe3G`\xdd'\xc1\f\xd8\x1e\xfe\\m\u00aa_Qc\xfc\x11\xba\xe8\bf\xc0N\xa3\x1b\xb5A\x1d0\xe5\xff\xf1\xaf\xb5:P\x9bw\xde\bf\xc0\xf5v\xa7i(\x1dp\xc0\x9f\xf1o\xb4 \xf7#U\x14\x00\x00\x02\xf4IDATx\xda|SkHSa\x18~\xce\u0659\xd3m\xce\xcd\xcdL\x99I\xf7D\xa2?QXYBBZ\x19i\xa8\xe4\r\xaa\x95\x18*\x95B\xa4T&\bQZa\x96\x81\x05I\x14R\x96\x81H\x17B\xbbHY\x16d\x14\xa5\xa2&\xe4e\xe66\xdd\u0699\xbb\x9c\xad\xef\x9cyL\xff\xf4\xfd\xfa.\xcf\xf3\xbc\xcfy\xde\xf7P\x98\xb7|>\x9f\xba\u007f\xd4}\xd1h\xf1&5<\xb5\xe9\xbf\x0e\xbb\x85\xfb\xd8%R\x18\x92\x94\xa3a!\x92\xe71Q\xd2R\x8a\xa2L\"\x87\x9a%\ua18c\x9e\x9a\x91I.\xf1z\x9b-\xb2\xf7\x97\x9f\xa8\x92\xd3\b`\x80I\xabW8\xaf\xd6Kq$Yi\x8c\xd0H\xda\u027e\x98\bMR&+\x1778\xeeyx\xa1y:b`\xcc3\xdf\x106\xc5\xc8\x10\xa9\x95\xa0\xb9\x93]p\xbfl1\x83\x924\xd5D\xb8F\x92N\xf5\x8d\xb8\x9e\x1c\xbclJb\x9d\xbe\x05\xa0\xd8h)\xf6m\x96#(\x80B\xd3k\x16=\x83\xae\x05\xef\xfc\xfd\x8d\"\xed\v\xc6\xe6\xf0\xe9Er}a(\xeaZm0\xecPb\xdd\xd2\x00\x98\xff\xf8\xadW\x1f\u0480wW\xd7j\xc5\xf1T\x15\xf2\xaf\x9a\xe0p\xf9`c\xbdzz\xcc\xcciE\xd5\xf2\xc6)\xd4\x15\x84B\xafc\xb0\xeb\xec\x04\xda{f\xd0\xf5\u0749\xdd\x15\x13$\x0f\n7\x8fiQF0\x1e\u038f\x1f1q:\xa6\xeb\x87S'\n\x90\x94A\x1c\x91\xe0(T\xe6\xaa!\x93R\xc2\xfe\\\x8e\x1a\xc1$\xd0q3G\xc4%0Z\xfc\n\xdd}N-\xf3y\xc0%\x15\x056\xac\n@\xdb\a\a\x1et\xdaq\xfb\x84\x0er\x19E:\x04\xc1\xae\xe1\x8a\t)\x1b\x83\x84`?\xf5\xfb\xf3\xe8\x19rS\u0328\x99\x9b\v\x86\xaf\x12\x1d\u01a0\"[\x8dp\xb5\x04\x8f\u07f1\u012e\x0f\xe9\xf1\n\x9c\xca\b\x81\xc7\xeb\u00f4\xdd;\x87\xff=\u0341\x11\xfb}\xfe\x80ZH\x96'\xde{i\x17B\xcb\u06ee\x10\x80w;\xec\xe0\ve%(0E\x82\xad1hp\xa9\xc5\xcag\xe0\x17\xb0\xb2^\x1c\xbdf\x16,7\x97\x87\xe1}\xaf\v\xfb\x13\xe4h\xebv\x80#\x0e\xb4*\x1a-oY\xe4'+q\xb8\xd62\x97\x01\xbf\x98\x8cx9{\xff\r+\xe7\x0f|;\xab\x9a\xa6Q[\xa0Ap\x10\x8d\xbc\xeaIp\xc4q\xd3I\x1d\u05af\x94\tU\xe7\x93\xf7\xc6\u025d\xd4O\xa3\xfb\xd9\xe9;S\x89\u07c6\u0774\xf8@D\x91\xb9U\x01\x9dJ\x02\x8a\f\xfb\x04\xf9V\xbe\x9d\u054f\xacs\xe45QRT\xe6\xa8;\x98\xe8ELjY\x9a\xac\xb7\xb0\x81\xd3[f\ag\xdb\xda@\xe4\x92\xea\xe2\x80\xf1\"\xb7\xc8\f\u0424\x84\xd7\xeb\xcf\xecLV\xc8\xe0\xf2\b&\x85&?\x04\xfb\xf1nmiU\xb6\xc2L\xd3\xff\x06j\xfeh\xf3\xad,i\xb0\bd\x1eS\x95\xab\xb4\x90\xb0w\x12\xae\x9d\x12A#&O\xe6\xab/3\xf5\u0126\x06\xffY\xc5{\x82m[b\x03\x8bVDJ\x1b\xf9\xf3_\x01\x06\x00\xf19?q\xaaE\xa0\xa4\x00\x00\x00\x00IEND\xaeB`\x82") func www_app_assets_img_icons_favicon_png_bytes() ([]byte, error) { return _www_app_assets_img_icons_favicon_png, nil } func www_app_assets_img_icons_favicon_png() (*asset, error) { bytes, err := www_app_assets_img_icons_favicon_png_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/icons/favicon.png", size: 1663, mode: os.FileMode(420), modTime: time.Unix(1429751137, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_icons_ic_arrow_forward_24px_svg = []byte(``) func www_app_assets_img_icons_ic_arrow_forward_24px_svg_bytes() ([]byte, error) { return _www_app_assets_img_icons_ic_arrow_forward_24px_svg, nil } func www_app_assets_img_icons_ic_arrow_forward_24px_svg() (*asset, error) { bytes, err := www_app_assets_img_icons_ic_arrow_forward_24px_svg_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/icons/ic_arrow_forward_24px.svg", size: 158, mode: os.FileMode(420), modTime: time.Unix(1429751137, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_icons_ic_cancel_24px_svg = []byte(``) func www_app_assets_img_icons_ic_cancel_24px_svg_bytes() ([]byte, error) { return _www_app_assets_img_icons_ic_cancel_24px_svg, nil } func www_app_assets_img_icons_ic_cancel_24px_svg() (*asset, error) { bytes, err := www_app_assets_img_icons_ic_cancel_24px_svg_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/icons/ic_cancel_24px.svg", size: 276, mode: os.FileMode(420), modTime: time.Unix(1429751137, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_icons_ic_close_24px_svg = []byte(``) func www_app_assets_img_icons_ic_close_24px_svg_bytes() ([]byte, error) { return _www_app_assets_img_icons_ic_close_24px_svg, nil } func www_app_assets_img_icons_ic_close_24px_svg() (*asset, error) { bytes, err := www_app_assets_img_icons_ic_close_24px_svg_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/icons/ic_close_24px.svg", size: 202, mode: os.FileMode(420), modTime: time.Unix(1429751137, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_icons_ic_menu_svg = []byte(` `) func www_app_assets_img_icons_ic_menu_svg_bytes() ([]byte, error) { return _www_app_assets_img_icons_ic_menu_svg, nil } func www_app_assets_img_icons_ic_menu_svg() (*asset, error) { bytes, err := www_app_assets_img_icons_ic_menu_svg_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/icons/ic_menu.svg", size: 791, mode: os.FileMode(420), modTime: time.Unix(1429751137, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_icons_ic_menu_24px_svg = []byte(` `) func www_app_assets_img_icons_ic_menu_24px_svg_bytes() ([]byte, error) { return _www_app_assets_img_icons_ic_menu_24px_svg, nil } func www_app_assets_img_icons_ic_menu_24px_svg() (*asset, error) { bytes, err := www_app_assets_img_icons_ic_menu_24px_svg_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/icons/ic_menu_24px.svg", size: 841, mode: os.FileMode(420), modTime: time.Unix(1429751137, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_icons_list_control_down_png = []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\x00\x000\b\x03\x00\x00\x00`\xdc\t\xb5\x00\x00\x00\x19tEXtSoftware\x00Adobe ImageReadyq\xc9e<\x00\x00\x00'PLTE\xa8\xa8\xa8\xfc\xfc\xfc\xc0\xc0\xc0\xb6\xb6\xb6\xf7\xf7\xf7\xaa\xaa\xaa\xf6\xf6\xf6\xe6\xe6\xe6\xe8\xe8\u8d75\xb5\xc3\xc3\xc3\xe5\xe5\xe5\xff\xff\xffZLu\xde\x00\x00\x00\rtRNS\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00=\xe8\"\x86\x00\x00\x00\x8bIDATx\xda\xec\xd4I\x12\x80 \fD\xd1\x04\x04\x9c\xee\u007f^\u02c1\xd2`\xb7\x96k\xc3\xd2\xfao\xa1\t\xca\xfc\xf1\x88\x03\a\xbf\x01}\xd7\x06\xb9\u007f\x02S\x8a\x8d\xc8C*\x1c\x94$bE\x1eD\xac0`\x14\xb1\"\xc7\xf5\xc9H\x81\x06+\xba\xad\x0f\xca\xdf\xc1\n\u0537_\xe9*`\u007f\x9b\xc3)p\u007f\x1f\\\x15\xa4\a\x93>\x04\xe9\xd1j\xec\x82\xf4p\x97\xaa@=^\xbe]\xc0\x9el\xeb*p\xcf\xd6[\x03\xe9\xe9}P\xf5\x9f\x80\x03\a\xafg\x11`\x00\xb0\xe4e\a\x17\x87\xea}\x00\x00\x00\x00IEND\xaeB`\x82") func www_app_assets_img_icons_list_control_down_png_bytes() ([]byte, error) { return _www_app_assets_img_icons_list_control_down_png, nil } func www_app_assets_img_icons_list_control_down_png() (*asset, error) { bytes, err := www_app_assets_img_icons_list_control_down_png_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/icons/list_control_down.png", size: 309, mode: os.FileMode(420), modTime: time.Unix(1429751137, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_img_kubernetes_svg = []byte(` `) func www_app_assets_img_kubernetes_svg_bytes() ([]byte, error) { return _www_app_assets_img_kubernetes_svg, nil } func www_app_assets_img_kubernetes_svg() (*asset, error) { bytes, err := www_app_assets_img_kubernetes_svg_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/img/kubernetes.svg", size: 11663, mode: os.FileMode(420), modTime: time.Unix(1429751137, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_js_gitkeep = []byte(``) func www_app_assets_js_gitkeep_bytes() ([]byte, error) { return _www_app_assets_js_gitkeep, nil } func www_app_assets_js_gitkeep() (*asset, error) { bytes, err := www_app_assets_js_gitkeep_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/js/.gitkeep", size: 0, mode: os.FileMode(420), modTime: time.Unix(1432754009, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_js_app_js = []byte(`var componentNamespaces = ["kubernetesApp.components.dashboard"]; // APP START // **************************** // /www/app/assets/app.js is autogenerated. Do not modify. // Changes should be made in /master/modules/js or /master/components//js // **************************** // ----------------------------------- var app = angular.module('kubernetesApp', [ 'ngRoute', 'ngMaterial', 'ngLodash', 'door3.css', 'kubernetesApp.config', 'kubernetesApp.services', 'angular.filter' ].concat(componentNamespaces)); app.factory('menu', [ '$location', '$rootScope', 'sections', '$route', function($location, $rootScope, sections, $route) { var self; $rootScope.$on('$locationChangeSuccess', onLocationChange); return self = { sections: sections, setSections: function(_sections) { this.sections = _sections; }, selectSection: function(section) { self.openedSection = section; }, toggleSelectSection: function(section) { self.openedSection = (self.openedSection === section ? null : section); }, isSectionSelected: function(section) { return self.openedSection === section; }, selectPage: function(section, page) { self.currentSection = section; self.currentPage = page; }, isPageSelected: function(page) { return self.currentPage === page; } }; function onLocationChange() { var path = $route.current.originalPath; var matchPage = function(section, page) { if (path === page.url || path === (page.url + '/')) { self.selectSection(section); self.selectPage(section, page); } }; sections.forEach(function(section) { if (section.children) { section.children.forEach(function(childSection) { if (childSection.pages) { childSection.pages.forEach(function(page) { matchPage(childSection, page); }); } }); } else if (section.pages) { section.pages.forEach(function(page) { matchPage(section, page); }); } else if (section.type === 'link') { matchPage(section, section); } }); } } ]); angular.module('kubernetesApp.config', []); angular.module('kubernetesApp.services', ['kubernetesApp.config']); app.config([ '$routeProvider', function($routeProvider) { $routeProvider.when("/404", {templateUrl: "views/partials/404.html"}) // else 404 .otherwise({redirectTo: "/404"}); } ]) .config([ '$routeProvider', 'manifestRoutes', function($routeProvider, manifestRoutes) { angular.forEach(manifestRoutes, function(r) { var route = { templateUrl: r.templateUrl }; if (r.controller) { route.controller = r.controller; } if (r.css) { route.css = r.css; } $routeProvider.when(r.url, route); }); } ]); app.value("sections", [{"name":"Dashboard","url":"/dashboard","type":"link","templateUrl":"/components/dashboard/pages/home.html"},{"name":"Dashboard","type":"heading","children":[{"name":"Dashboard","type":"toggle","url":"/dashboard","templateUrl":"/components/dashboard/pages/home.html","pages":[{"name":"Pods","url":"/dashboard/pods","templateUrl":"/components/dashboard/views/listPods.html","type":"link"},{"name":"Pod Visualizer","url":"/dashboard/visualpods","templateUrl":"/components/dashboard/views/listPodsVisualizer.html","type":"link"},{"name":"Services","url":"/dashboard/services","templateUrl":"/components/dashboard/views/listServices.html","type":"link"},{"name":"Replication Controllers","url":"/dashboard/replicationcontrollers","templateUrl":"/components/dashboard/views/listReplicationControllers.html","type":"link"},{"name":"Events","url":"/dashboard/events","templateUrl":"/components/dashboard/views/listEvents.html","type":"link"},{"name":"Nodes","url":"/dashboard/nodes","templateUrl":"/components/dashboard/views/listMinions.html","type":"link"},{"name":"Replication Controller","url":"/dashboard/replicationcontrollers/:replicationControllerId","templateUrl":"/components/dashboard/views/replication.html","type":"link"},{"name":"Service","url":"/dashboard/services/:serviceId","templateUrl":"/components/dashboard/views/service.html","type":"link"},{"name": "Node","url": "/dashboard/nodes/:nodeId","templateUrl": "/components/dashboard/views/node.html","type": "link"},{"name":"Explore","url":"/dashboard/groups/:grouping*?/selector/:selector*?","templateUrl":"/components/dashboard/views/groups.html","type":"link"},{"name":"Pod","url":"/dashboard/pods/:podId","templateUrl":"/components/dashboard/views/pod.html","type":"link"}]}]},{"name":"Graph","url":"/graph","type":"link","templateUrl":"/components/graph/pages/home.html"},{"name":"Graph","url":"/graph/inspect","type":"link","templateUrl":"/components/graph/pages/inspect.html","css":"/components/graph/css/show-details-table.css"},{"name":"Graph","type":"heading","children":[{"name":"Graph","type":"toggle","url":"/graph","templateUrl":"/components/graph/pages/home.html","pages":[{"name":"Test","url":"/graph/test","type":"link","templateUrl":"/components/graph/pages/home.html"}]}]}]); app.directive('includeReplace', function() { 'use strict'; return { require: 'ngInclude', restrict: 'A', /* optional */ link: function(scope, el, attrs) { el.replaceWith(el.children()); } }; }) .directive('compile', ["$compile", function($compile) { 'use strict'; return function(scope, element, attrs) { scope.$watch(function(scope) { return scope.$eval(attrs.compile); }, function(value) { element.html(value); $compile(element.contents())(scope); }); }; }]) .directive("kubernetesUiMenu", function() { 'use strict'; return { templateUrl: "views/partials/kubernetes-ui-menu.tmpl.html" }; }) .directive('menuToggle', function() { 'use strict'; return { scope: {section: '='}, templateUrl: 'views/partials/menu-toggle.tmpl.html', link: function($scope, $element) { var controller = $element.parent().controller(); $scope.isOpen = function() { return controller.isOpen($scope.section); }; $scope.toggle = function() { controller.toggleOpen($scope.section); }; var parentNode = $element[0].parentNode.parentNode.parentNode; if (parentNode.classList.contains('parent-list-item')) { var heading = parentNode.querySelector('h2'); $element[0].firstChild.setAttribute('aria-describedby', heading.id); } } }; }); app.filter('startFrom', function() { 'use strict'; return function(input, start) { return input.slice(start); }; }) .filter('nospace', function() { 'use strict'; return function(value) { return (!value) ? '' : value.replace(/ /g, ''); }; }); app.run(['$route', angular.noop]) .run(["lodash", function(lodash) { // Alias lodash window['_'] = lodash; }]); app.service('SidebarService', [ '$rootScope', function($rootScope) { var service = this; service.sidebarItems = []; service.clearSidebarItems = function() { service.sidebarItems = []; }; service.renderSidebar = function() { var _entries = ''; service.sidebarItems.forEach(function(entry) { _entries += entry.Html; }); if (_entries) { $rootScope.sidenavLeft = '
' + _entries + '
'; } }; service.addSidebarItem = function(item) { service.sidebarItems.push(item); service.sidebarItems.sort(function(a, b) { return (a.order > b.order) ? 1 : ((b.order > a.order) ? -1 : 0); }); }; } ]); app.value("tabs", [{"component":"dashboard","title":"Dashboard"}]); app.constant("manifestRoutes", [{"description":"Dashboard visualization.","url":"/dashboard/","templateUrl":"components/dashboard/pages/home.html"},{"description":"Pods","url":"/dashboard/pods","templateUrl":"components/dashboard/views/listPods.html"},{"description":"Pod Visualizer","url":"/dashboard/visualpods","templateUrl":"components/dashboard/views/listPodsVisualizer.html"},{"description":"Services","url":"/dashboard/services","templateUrl":"components/dashboard/views/listServices.html"},{"description":"Replication Controllers","url":"/dashboard/replicationcontrollers","templateUrl":"components/dashboard/views/listReplicationControllers.html"},{"description":"Events","url":"/dashboard/events","templateUrl":"components/dashboard/views/listEvents.html"},{"description":"Nodes","url":"/dashboard/nodes","templateUrl":"components/dashboard/views/listMinions.html"},{"description":"Replication Controller","url":"/dashboard/replicationcontrollers/:replicationControllerId","templateUrl":"components/dashboard/views/replication.html"},{"description":"Service","url":"/dashboard/services/:serviceId","templateUrl":"components/dashboard/views/service.html"},{"description":"Node","url":"/dashboard/nodes/:nodeId","templateUrl":"components/dashboard/views/node.html"},{"description":"Explore","url":"/dashboard/groups/:grouping*?/selector/:selector*?","templateUrl":"components/dashboard/views/groups.html"},{"description":"Pod","url":"/dashboard/pods/:podId","templateUrl":"components/dashboard/views/pod.html"}]); angular.module("kubernetesApp.config", []) .constant("ENV", { "/": { "k8sApiServer": "/api/v1beta2", "k8sApiv1beta3Server": "/api/v1beta3", "k8sDataServer": "/cluster", "k8sDataPollMinIntervalSec": 10, "k8sDataPollMaxIntervalSec": 120, "k8sDataPollErrorThreshold": 5, "cAdvisorProxy": "", "cAdvisorPort": "4194" } }) .constant("ngConstant", true) ; /**========================================================= * Module: config.js * App routes and resources configuration =========================================================*/ /**========================================================= * Module: constants.js * Define constants to inject across the application =========================================================*/ /**========================================================= * Module: home-page.js * Page Controller =========================================================*/ app.controller('PageCtrl', [ '$scope', '$timeout', '$mdSidenav', 'menu', '$rootScope', function($scope, $timeout, $mdSidenav, menu, $rootScope) { $scope.menu = menu; $scope.path = path; $scope.goHome = goHome; $scope.openMenu = openMenu; $rootScope.openMenu = openMenu; $scope.closeMenu = closeMenu; $scope.isSectionSelected = isSectionSelected; $rootScope.$on('$locationChangeSuccess', openPage); // Methods used by menuLink and menuToggle directives this.isOpen = isOpen; this.isSelected = isSelected; this.toggleOpen = toggleOpen; this.shouldLockOpen = shouldLockOpen; $scope.toggleKubernetesUiMenu = toggleKubernetesUiMenu; var mainContentArea = document.querySelector("[role='main']"); var kubernetesUiMenu = document.querySelector("[role='kubernetes-ui-menu']"); // ********************* // Internal methods // ********************* var _t = false; $scope.showKubernetesUiMenu = false; function shouldLockOpen() { return _t; } function toggleKubernetesUiMenu() { $scope.showKubernetesUiMenu = !$scope.showKubernetesUiMenu; } function closeMenu() { $timeout(function() { $mdSidenav('left').close(); }); } function openMenu() { $timeout(function() { _t = !$mdSidenav('left').isOpen(); $mdSidenav('left').toggle(); }); } function path() { return $location.path(); } function goHome($event) { menu.selectPage(null, null); $location.path( '/' ); } function openPage() { $scope.closeMenu(); mainContentArea.focus(); } function isSelected(page) { return menu.isPageSelected(page); } function isSectionSelected(section) { var selected = false; var openedSection = menu.openedSection; if(openedSection === section){ selected = true; } else if(section.children) { section.children.forEach(function(childSection) { if(childSection === openedSection){ selected = true; } }); } return selected; } function isOpen(section) { return menu.isSectionSelected(section); } function toggleOpen(section) { menu.toggleSelectSection(section); } } ]).filter('humanizeDoc', function() { return function(doc) { if (!doc) return; if (doc.type === 'directive') { return doc.name.replace(/([A-Z])/g, function($1) { return '-'+$1.toLowerCase(); }); } return doc.label || doc.name; }; }); /**========================================================= * Module: main.js * Main Application Controller =========================================================*/ /**========================================================= * Module: tabs-global.js * Page Controller =========================================================*/ app.controller('TabCtrl', [ '$scope', '$location', 'tabs', function($scope, $location, tabs) { $scope.tabs = tabs; $scope.switchTab = function(index) { var location_path = $location.path(); var tab = tabs[index]; if (tab) { var path = '/%s'.format(tab.component); if (location_path.indexOf(path) == -1) { $location.path(path); } } }; } ]); /**========================================================= * Module: sidebar.js * Wraps the sidebar and handles collapsed state =========================================================*/ (function() { "use strict"; angular.module('kubernetesApp.services') .service('cAdvisorService', ["$http", "$q", "ENV", function($http, $q, ENV) { var _baseUrl = function(minionIp) { var minionPort = ENV['/']['cAdvisorPort'] || "8081"; var proxy = ENV['/']['cAdvisorProxy'] || "/api/v1beta3/proxy/nodes/"; return proxy + minionIp + ':' + minionPort + '/api/v1.0/'; }; this.getMachineInfo = getMachineInfo; function getMachineInfo(minionIp) { var fullUrl = _baseUrl(minionIp) + 'machine'; var deferred = $q.defer(); // hack $http.get(fullUrl).success(function(data) { deferred.resolve(data); }).error(function(data, status) { deferred.reject('There was an error') }); return deferred.promise; } this.getContainerInfo = getContainerInfo; // containerId optional function getContainerInfo(minionIp, containerId) { containerId = (typeof containerId === "undefined") ? "/" : containerId; var fullUrl = _baseUrl(minionIp) + 'containers' + containerId; var deferred = $q.defer(); var request = { "num_stats": 10, "num_samples": 0 }; $http.post(fullUrl, request) .success(function(data) { deferred.resolve(data); }) .error(function() { deferred.reject('There was an error') }); return deferred.promise; } this.getDataForMinion = function(minionIp) { var machineData, containerData; var deferred = $q.defer(); var p = $q.all([getMachineInfo(minionIp), getContainerInfo(minionIp)]) .then( function(dataArray) { machineData = dataArray[0]; containerData = dataArray[1]; var memoryData = parseMemory(machineData, containerData); var cpuData = parseCpu(machineData, containerData); var fsData = parseFilesystems(machineData, containerData); deferred.resolve({ memoryData: memoryData, cpuData: cpuData, filesystemData: fsData, machineData: machineData, containerData: containerData }); }, function(errorData) { deferred.reject(errorData); }); return deferred.promise; }; // Utils to process cadvisor data function humanize(num, size, units) { var unit; for (unit = units.pop(); units.length && num >= size; unit = units.pop()) { num /= size; } return [num, unit]; } // Following the IEC naming convention function humanizeIEC(num) { var ret = humanize(num, 1024, ["TiB", "GiB", "MiB", "KiB", "Bytes"]); return ret[0].toFixed(2) + " " + ret[1]; } // Following the Metric naming convention function humanizeMetric(num) { var ret = humanize(num, 1000, ["TB", "GB", "MB", "KB", "Bytes"]); return ret[0].toFixed(2) + " " + ret[1]; } function hasResource(stats, resource) { return stats.stats.length > 0 && stats.stats[0][resource]; } // Gets the length of the interval in nanoseconds. function getInterval(current, previous) { var cur = new Date(current); var prev = new Date(previous); // ms -> ns. return (cur.getTime() - prev.getTime()) * 1000000; } function parseCpu(machineInfo, containerInfo) { var cur = containerInfo.stats[containerInfo.stats.length - 1]; var results = []; var cpuUsage = 0; if (containerInfo.spec.has_cpu && containerInfo.stats.length >= 2) { var prev = containerInfo.stats[containerInfo.stats.length - 2]; var rawUsage = cur.cpu.usage.total - prev.cpu.usage.total; var intervalInNs = getInterval(cur.timestamp, prev.timestamp); // Convert to millicores and take the percentage cpuUsage = Math.round(((rawUsage / intervalInNs) / machineInfo.num_cores) * 100); if (cpuUsage > 100) { cpuUsage = 100; } } return { cpuPercentUsage: cpuUsage }; } function parseFilesystems(machineInfo, containerInfo) { var cur = containerInfo.stats[containerInfo.stats.length - 1]; if (!cur.filesystem) { return; } var filesystemData = []; for (var i = 0; i < cur.filesystem.length; i++) { var data = cur.filesystem[i]; var totalUsage = Math.floor((data.usage * 100.0) / data.capacity); var f = { device: data.device, filesystemNumber: i + 1, usage: data.usage, usageDescription: humanizeMetric(data.usage), capacity: data.capacity, capacityDescription: humanizeMetric(data.capacity), totalUsage: Math.floor((data.usage * 100.0) / data.capacity) }; filesystemData.push(f); } return filesystemData; } var oneMegabyte = 1024 * 1024; var oneGigabyte = 1024 * oneMegabyte; function parseMemory(machineInfo, containerInfo) { if (containerInfo.spec.has_memory && !hasResource(containerInfo, "memory")) { return; } // var titles = ["Time", "Total", "Hot"]; var data = []; for (var i = 0; i < containerInfo.stats.length; i++) { var cur = containerInfo.stats[i]; var elements = []; elements.push(cur.timestamp); elements.push(cur.memory.usage / oneMegabyte); elements.push(cur.memory.working_set / oneMegabyte); data.push(elements); } // Get the memory limit, saturate to the machine size. var memory_limit = machineInfo.memory_capacity; if (containerInfo.spec.memory.limit && (containerInfo.spec.memory.limit < memory_limit)) { memory_limit = containerInfo.spec.memory.limit; } var cur = containerInfo.stats[containerInfo.stats.length - 1]; var r = { current: { memoryUsage: cur.memory.usage, workingMemoryUsage: cur.memory.working_set, memoryLimit: memory_limit, memoryUsageDescription: humanizeMetric(cur.memory.usage), workingMemoryUsageDescription: humanizeMetric(cur.memory.working_set), memoryLimitDescription: humanizeMetric(memory_limit) }, historical: data }; return r; } }]); })(); app.provider('k8sApi', function() { var urlBase = ''; this.setUrlBase = function(value) { urlBase = value; }; var _get = function($http, baseUrl, query) { var _fullUrl = baseUrl; if (query !== undefined) { _fullUrl += '/' + query; } return $http.get(_fullUrl); }; this.$get = ["$http", "$q", function($http, $q) { var api = {}; api.getUrlBase = function() { return urlBase; }; api.getPods = function(query) { return _get($http, urlBase + '/pods', query); }; api.getMinions = function(query) { return _get($http, urlBase + '/nodes', query); }; api.getNodes = api.getMinions; api.getServices = function(query) { return _get($http, urlBase + '/services', query); }; api.getReplicationControllers = function(query) { return _get($http, urlBase + '/replicationControllers', query) }; api.getEvents = function(query) { return _get($http, urlBase + '/events', query); }; return api; }]; }) .config(["k8sApiProvider", "ENV", function(k8sApiProvider, ENV) { if (ENV && ENV['/'] && ENV['/']['k8sApiServer']) { var proxy = ENV['/']['cAdvisorProxy'] || ''; k8sApiProvider.setUrlBase(proxy + ENV['/']['k8sApiServer']); } }]); app.provider('k8sv1Beta3Api', function() { var urlBase = ''; var _namespace = 'default'; this.setUrlBase = function(value) { urlBase = value; }; this.setNamespace = function(value) { _namespace = value; }; this.getNamespace = function() { return _namespace; }; var _get = function($http, baseUrl, query) { var _fullUrl = baseUrl; if (query !== undefined) { _fullUrl += '/' + query; } return $http.get(_fullUrl); }; this.$get = ["$http", "$q", function($http, $q) { var api = {}; api.getUrlBase = function() { return urlBase + '/namespaces/' + _namespace; }; api.getPods = function(query) { return _get($http, api.getUrlBase() + '/pods', query); }; api.getNodes = function(query) { return _get($http, urlBase + '/nodes', query); }; api.getMinions = api.getNodes; api.getServices = function(query) { return _get($http, api.getUrlBase() + '/services', query); }; api.getReplicationControllers = function(query) { return _get($http, api.getUrlBase() + '/replicationcontrollers', query) }; api.getEvents = function(query) { return _get($http, api.getUrlBase() + '/events', query); }; return api; }]; }) .config(["k8sv1Beta3ApiProvider", "ENV", function(k8sv1Beta3ApiProvider, ENV) { if (ENV && ENV['/'] && ENV['/']['k8sApiv1beta3Server']) { var proxy = ENV['/']['cAdvisorProxy'] || ''; k8sv1Beta3ApiProvider.setUrlBase(proxy + ENV['/']['k8sApiv1beta3Server']); } }]); (function() { "use strict"; var pollK8sDataServiceProvider = function PollK8sDataServiceProvider(_) { // A set of configuration controlling the polling behavior. // Their values should be configured in the application before // creating the service instance. var useSampleData = false; this.setUseSampleData = function(value) { useSampleData = value; }; var sampleDataFiles = ["shared/assets/sampleData1.json"]; this.setSampleDataFiles = function(value) { sampleDataFiles = value; }; var dataServer = "http://localhost:5555/cluster"; this.setDataServer = function(value) { dataServer = value; }; var pollMinIntervalSec = 10; this.setPollMinIntervalSec = function(value) { pollMinIntervalSec = value; }; var pollMaxIntervalSec = 120; this.setPollMaxIntervalSec = function(value) { pollMaxIntervalSec = value; }; var pollErrorThreshold = 5; this.setPollErrorThreshold = function(value) { pollErrorThreshold = value; }; this.$get = function($http, $timeout) { // Now the sequenceNumber will be used for debugging and verification purposes. var k8sdatamodel = { "data": undefined, "sequenceNumber": 0, "useSampleData": useSampleData }; var pollingError = 0; var promise = undefined; // Implement fibonacci back off when the service is down. var pollInterval = pollMinIntervalSec; var pollIncrement = pollInterval; // Reset polling interval. var resetCounters = function() { pollInterval = pollMinIntervalSec; pollIncrement = pollInterval; }; // Bump error count and polling interval. var bumpCounters = function() { // Bump the error count. pollingError++; // TODO: maybe display an error in the UI to the end user. if (pollingError % pollErrorThreshold === 0) { console.log("Error: " + pollingError + " consecutive polling errors for " + dataServer + "."); } // Bump the polling interval. var oldIncrement = pollIncrement; pollIncrement = pollInterval; pollInterval += oldIncrement; // Reset when limit reached. if (pollInterval > pollMaxIntervalSec) { resetCounters(); } }; var updateModel = function(newModel) { var dedupe = function(dataModel) { if (dataModel.resources) { dataModel.resources = _.uniq(dataModel.resources, function(resource) { return resource.id; }); } if (dataModel.relations) { dataModel.relations = _.uniq(dataModel.relations, function(relation) { return relation.source + relation.target; }); } }; dedupe(newModel); var newModelString = JSON.stringify(newModel); var oldModelString = ""; if (k8sdatamodel.data) { oldModelString = JSON.stringify(k8sdatamodel.data); } if (newModelString !== oldModelString) { k8sdatamodel.data = newModel; k8sdatamodel.sequenceNumber++; } pollingError = 0; resetCounters(); }; var nextSampleDataFile = 0; var getSampleDataFile = function() { var result = ""; if (sampleDataFiles.length > 0) { result = sampleDataFiles[nextSampleDataFile % sampleDataFiles.length]; ++nextSampleDataFile; } return result; }; var pollOnce = function(scope, repeat) { var dataSource = (k8sdatamodel.useSampleData) ? getSampleDataFile() : dataServer; $.getJSON(dataSource) .done(function(newModel, jqxhr, textStatus) { if (newModel && newModel.success) { delete newModel.success; // Remove success indicator. delete newModel.timestamp; // Remove changing timestamp. updateModel(newModel); scope.$apply(); promise = repeat ? $timeout(function() { pollOnce(scope, true); }, pollInterval * 1000) : undefined; return; } bumpCounters(); promise = repeat ? $timeout(function() { pollOnce(scope, true); }, pollInterval * 1000) : undefined; }) .fail(function(jqxhr, textStatus, error) { bumpCounters(); promise = repeat ? $timeout(function() { pollOnce(scope, true); }, pollInterval * 1000) : undefined; }); }; var isPolling = function() { return promise ? true : false; }; var start = function(scope) { // If polling has already started, then calling start() again would // just reset the counters and polling interval, but it will not // start a new thread polling in parallel to the existing polling // thread. resetCounters(); if (!promise) { k8sdatamodel.data = undefined; pollOnce(scope, true); } }; var stop = function() { if (promise) { $timeout.cancel(promise); promise = undefined; } }; var refresh = function(scope) { stop(scope); resetCounters(); k8sdatamodel.data = undefined; pollOnce(scope, false); }; return { "k8sdatamodel": k8sdatamodel, "isPolling": isPolling, "refresh": refresh, "start": start, "stop": stop }; }; }; angular.module("kubernetesApp.services") .provider("pollK8sDataService", ["lodash", pollK8sDataServiceProvider]) .config(["pollK8sDataServiceProvider", "ENV", function(pollK8sDataServiceProvider, ENV) { if (ENV && ENV['/']) { if (ENV['/']['k8sDataServer']) { pollK8sDataServiceProvider.setDataServer(ENV['/']['k8sDataServer']); } if (ENV['/']['k8sDataPollIntervalMinSec']) { pollK8sDataServiceProvider.setPollIntervalSec(ENV['/']['k8sDataPollIntervalMinSec']); } if (ENV['/']['k8sDataPollIntervalMaxSec']) { pollK8sDataServiceProvider.setPollIntervalSec(ENV['/']['k8sDataPollIntervalMaxSec']); } if (ENV['/']['k8sDataPollErrorThreshold']) { pollK8sDataServiceProvider.setPollErrorThreshold(ENV['/']['k8sDataPollErrorThreshold']); } } }]); }()); /**========================================================= * Module: toggle-state.js * Services to share toggle state functionality =========================================================*/ app.controller('cAdvisorController', [ '$scope', '$routeParams', 'k8sApi', 'lodash', 'cAdvisorService', '$q', '$interval', function($scope, $routeParams, k8sApi, lodash, cAdvisorService, $q, $interval) { $scope.k8sApi = k8sApi; $scope.activeMinionDataById = {}; $scope.maxDataByById = {}; $scope.getData = function() { $scope.loading = true; k8sApi.getMinions().success(angular.bind(this, function(res) { $scope.minions = res; // console.log(res); var promises = lodash.map(res.items, function(m) { return cAdvisorService.getDataForMinion(m.id); }); $q.all(promises).then( function(dataArray) { lodash.each(dataArray, function(data, i) { var m = res.items[i]; var maxData = maxMemCpuInfo(m.id, data.memoryData, data.cpuData, data.filesystemData); // console.log("maxData", maxData); $scope.activeMinionDataById[m.id] = transformMemCpuInfo(data.memoryData, data.cpuData, data.filesystemData, maxData, m.hostIP) }); }, function(errorData) { // console.log("Error: " + errorData); $scope.loading = false; }); $scope.loading = false; })).error(angular.bind(this, this.handleError)); }; function getcAdvisorDataForMinion(m) { var p = cAdvisorService.getDataForMinion(m.hostIP); return p; } function handleError(data, status, headers, config) { // console.log("Error (" + status + "): " + data); $scope.loading = false; }; // d3 function getColorForIndex(i, percentage) { // var colors = ['red', 'blue', 'yellow', 'pink', 'purple', 'green', 'orange']; // return colors[i]; var c = "color-" + (i + 1); if (percentage && percentage >= 90) c = c + ' color-critical'; else if (percentage && percentage >= 80) c = c + ' color-warning'; return c; } function getMaxColorForIndex(i, percentage) { // var colors = ['red', 'blue', 'yellow', 'pink', 'purple', 'green', 'orange']; // return colors[i]; var c = "color-max-" + (i + 1); if (percentage && percentage >= 90) c = c + ' color-max-critical'; else if (percentage && percentage >= 80) c = c + ' color-max-warning'; return c; } function maxMemCpuInfo(mId, mem, cpu, fsDataArray) { if ($scope.maxDataByById[mId] === undefined) $scope.maxDataByById[mId] = {}; var currentMem = mem.current; var currentCpu = cpu; var items = []; if ($scope.maxDataByById[mId]['cpu'] === undefined || $scope.maxDataByById[mId]['cpu'] < currentCpu.cpuPercentUsage) { // console.log("New max cpu " + mId, $scope.maxDataByById[mId].cpu, currentCpu.cpuPercentUsage); $scope.maxDataByById[mId]['cpu'] = currentCpu.cpuPercentUsage; } items.push({ maxValue: $scope.maxDataByById[mId]['cpu'], maxTickClassNames: getColorForIndex(0, $scope.maxDataByById[mId]['cpu']), maxClassNames: getMaxColorForIndex(0, $scope.maxDataByById[mId]['cpu']) }); var memPercentage = Math.floor((currentMem.memoryUsage * 100.0) / currentMem.memoryLimit); if ($scope.maxDataByById[mId]['mem'] === undefined || $scope.maxDataByById[mId]['mem'] < memPercentage) $scope.maxDataByById[mId]['mem'] = memPercentage; items.push({ maxValue: $scope.maxDataByById[mId]['mem'], maxTickClassNames: getColorForIndex(1, $scope.maxDataByById[mId]['mem']), maxClassNames: getMaxColorForIndex(1, $scope.maxDataByById[mId]['mem']) }); for (var i = 0; i < fsDataArray.length; i++) { var f = fsDataArray[i]; var fid = 'FS #' + f.filesystemNumber; if ($scope.maxDataByById[mId][fid] === undefined || $scope.maxDataByById[mId][fid] < f.totalUsage) $scope.maxDataByById[mId][fid] = f.totalUsage; items.push({ maxValue: $scope.maxDataByById[mId][fid], maxTickClassNames: getColorForIndex(2 + i, $scope.maxDataByById[mId][fid]), maxClassNames: getMaxColorForIndex(2 + i, $scope.maxDataByById[mId][fid]) }); } // console.log("Max Data is now " + mId, $scope.maxDataByById[mId]); return items; } function transformMemCpuInfo(mem, cpu, fsDataArray, maxData, hostName) { var currentMem = mem.current; var currentCpu = cpu; var items = []; items.push({ label: 'CPU', stats: currentCpu.cpuPercentUsage + '%', value: currentCpu.cpuPercentUsage, classNames: getColorForIndex(0, currentCpu.cpuPercentUsage), maxData: maxData[0], hostName: hostName }); var memPercentage = Math.floor((currentMem.memoryUsage * 100.0) / currentMem.memoryLimit); items.push({ label: 'Memory', stats: currentMem.memoryUsageDescription + ' / ' + currentMem.memoryLimitDescription, value: memPercentage, classNames: getColorForIndex(1, memPercentage), maxData: maxData[1], hostName: hostName }); for (var i = 0; i < fsDataArray.length; i++) { var f = fsDataArray[i]; items.push({ label: 'FS #' + f.filesystemNumber, stats: f.usageDescription + ' / ' + f.capacityDescription, value: f.totalUsage, classNames: getColorForIndex(2 + i, f.totalUsage), maxData: maxData[2 + i], hostName: hostName }); } var a = []; var segments = { segments: items }; a.push(segments); return a; }; // end d3 var promise = $interval($scope.getData, 3000); // Cancel interval on page changes $scope.$on('$destroy', function() { if (angular.isDefined(promise)) { $interval.cancel(promise); promise = undefined; } }); $scope.getData(); } ]); /**========================================================= * Module: Dashboard * Visualizer for clusters =========================================================*/ app.controller('DashboardCtrl', ['$scope', function($scope) {}]); /**========================================================= * Module: Group * Visualizer for groups =========================================================*/ app.controller('GroupCtrl', [ '$scope', '$route', '$interval', '$routeParams', 'k8sv1Beta3Api', '$rootScope', '$location', 'lodash', function($scope, $route, $interval, $routeParams, k8sApi, $rootScope, $location, _) { 'use strict'; $scope.doTheBack = function() { window.history.back(); }; $scope.capitalize = function(s) { return _.capitalize(s); }; $rootScope.doTheBack = $scope.doTheBack; $scope.resetGroupLayout = function(group) { delete group.settings; }; $scope.handlePath = function(path) { var parts = path.split("/"); // split leaves an empty string at the beginning. parts = parts.slice(1); if (parts.length === 0) { return; } this.handleGroups(parts.slice(1)); }; $scope.getState = function(obj) { return Object.keys(obj)[0]; }; $scope.clearSelector = function(grouping) { $location.path("/dashboard/groups/" + grouping + "/selector/"); }; $scope.changeGroupBy = function() { var grouping = $scope.selectedGroupBy; var s = _.clone($location.search()); if ($scope.routeParams.grouping != grouping) $location.path("/dashboard/groups/" + grouping + "/selector/").search(s); }; $scope.createBarrier = function(count, callback) { var barrier = count; var barrierFunction = angular.bind(this, function(data) { // JavaScript is single threaded so this is safe. barrier--; if (barrier === 0) { if (callback) { callback(); } } }); return barrierFunction; }; $scope.handleGroups = function(parts, selector) { $scope.groupBy = parts; $scope.loading = true; $scope.selector = selector; var args = []; var type = ""; if (selector && selector.length > 0) { $scope.selectorPieces = selector.split(","); var labels = []; var fields = []; for (var i = 0; i < $scope.selectorPieces.length; i++) { var piece = $scope.selectorPieces[i]; if (piece[0] == '$') { fields.push(piece.slice(2)); } else { if (piece.indexOf("type=") === 0) { var labelParts = piece.split("="); if (labelParts.length > 1) { type = labelParts[1]; } } else { labels.push(piece); } } } if (labels.length > 0) { args.push("labels=" + encodeURI(labels.join(","))); } if (fields.length > 0) { args.push("fields=" + encodeURI(fields.join(","))); } } var query = "?" + args.join("&"); var list = []; var count = type.length > 0 ? 1 : 3; var barrier = $scope.createBarrier(count, function() { $scope.groups = $scope.groupData(list, 0); $scope.loading = false; $scope.groupByOptions = buildGroupByOptions(); $scope.selectedGroupBy = $routeParams.grouping; }); if (type === "" || type == "pod") { k8sApi.getPods(query).success(function(data) { $scope.addLabel("type", "pod", data.items); for (var i = 0; data.items && i < data.items.length; ++i) { data.items[i].metadata.labels.host = data.items[i].spec.host; list.push(data.items[i]); } barrier(); }).error($scope.handleError); } if (type === "" || type == "service") { k8sApi.getServices(query).success(function(data) { $scope.addLabel("type", "service", data.items); for (var i = 0; data.items && i < data.items.length; ++i) { list.push(data.items[i]); } barrier(); }).error($scope.handleError); } if (type === "" || type == "replicationController") { k8sApi.getReplicationControllers(query).success(angular.bind(this, function(data) { $scope.addLabel("type", "replicationController", data.items); for (var i = 0; data.items && i < data.items.length; ++i) { list.push(data.items[i]); } barrier(); })).error($scope.handleError); } }; $scope.addLabel = function(key, value, items) { if (!items) { return; } for (var i = 0; i < items.length; i++) { if (!items[i].metadata.labels) { items[i].metadata.labels = []; } items[i].metadata.labels[key] = value; } }; $scope.groupData = function(items, index) { var result = { "items": {}, "kind": "grouping" }; for (var i = 0; i < items.length; i++) { key = items[i].metadata.labels[$scope.groupBy[index]]; if (!key) { key = ""; } var list = result.items[key]; if (!list) { list = []; result.items[key] = list; } list.push(items[i]); } if (index + 1 < $scope.groupBy.length) { for (var key in result.items) { result.items[key] = $scope.groupData(result.items[key], index + 1); } } return result; }; $scope.getGroupColor = function(type) { if (type === 'pod') { return '#6193F0'; } else if (type === 'replicationController') { return '#E008FE'; } else if (type === 'service') { return '#7C43FF'; } }; var groups = $routeParams.grouping; if (!groups) { groups = ''; } $scope.routeParams = $routeParams; $scope.route = $route; $scope.handleGroups(groups.split('/'), $routeParams.selector); $scope.handleError = function(data, status, headers, config) { console.log("Error (" + status + "): " + data); $scope_.loading = false; }; function getDefaultGroupByOptions() { return [{name: 'Type', value: 'type'}, {name: 'Name', value: 'name'}]; } function buildGroupByOptions() { var g = $scope.groups; var options = getDefaultGroupByOptions(); var newOptions = _.map(g.items, function(vals) { return _.map(vals, function(v) { return _.keys(v.metadata.labels); }); }); newOptions = _.reject(_.uniq(_.flattenDeep(newOptions)), function(o) { return o == 'name' || o == 'type' || o == ""; }); newOptions = _.map(newOptions, function(o) { return { name: o, value: o }; }); options = options.concat(newOptions); return options; } $scope.changeFilterBy = function(selector) { var grouping = $scope.selectedGroupBy; var s = _.clone($location.search()); if ($scope.routeParams.selector != selector) $location.path("/dashboard/groups/" + $scope.routeParams.grouping + "/selector/" + selector).search(s); }; } ]); /**========================================================= * Module: Header * Visualizer for clusters =========================================================*/ angular.module('kubernetesApp.components.dashboard', []) .controller('HeaderCtrl', [ '$scope', '$location', function($scope, $location) { 'use strict'; $scope.$watch('Pages', function(newValue, oldValue) { if (typeof newValue !== 'undefined') { $location.path(newValue); } }); $scope.subPages = [ {category: 'dashboard', name: 'Explore', value: '/dashboard/groups/type/selector/'}, {category: 'dashboard', name: 'Pods', value: '/dashboard/pods'}, {category: 'dashboard', name: 'Nodes', value: '/dashboard/nodes'}, {category: 'dashboard', name: 'Replication Controllers', value: '/dashboard/replicationcontrollers'}, {category: 'dashboard', name: 'Services', value: '/dashboard/services'}, {category: 'dashboard', name: 'Events', value: '/dashboard/events'} ]; } ]); /**========================================================= * Module: List Events * Visualizer list events =========================================================*/ app.controller('ListEventsCtrl', [ '$scope', '$routeParams', 'k8sv1Beta3Api', '$location', '$filter', function($scope, $routeParams, k8sApi, $location, $filter) { 'use strict'; $scope.getData = getData; $scope.loading = true; $scope.k8sApi = k8sApi; $scope.pods = null; $scope.groupedPods = null; $scope.serverView = false; $scope.headers = [ {name: 'First Seen', field: 'firstSeen'}, {name: 'Last Seen', field: 'lastSeen'}, {name: 'Count', field: 'count'}, {name: 'Name', field: 'name'}, {name: 'Kind', field: 'kind'}, {name: 'SubObject', field: 'subObject'}, {name: 'Reason', field: 'reason'}, {name: 'Source', field: 'source'}, {name: 'Message', field: 'message'} ]; $scope.sortable = ['firstSeen', 'lastSeen', 'count', 'name', 'kind', 'subObject', 'reason', 'source']; $scope.count = 10; function handleError(data, status, headers, config) { console.log("Error (" + status + "): " + data); $scope.loading = false; } $scope.content = []; function getData() { $scope.loading = true; k8sApi.getEvents().success(function(data) { $scope.loading = false; var _fixComma = function(str) { if (str.substring(0, 1) == ',') { return str.substring(1); } else { return str; } }; data.items.forEach(function(event) { var _sources = ''; if (event.source) { _sources = event.source.component + ' ' + event.source.host; } $scope.content.push({ firstSeen: $filter('date')(event.firstTimestamp, 'medium'), lastSeen: $filter('date')(event.lastTimestamp, 'medium'), count: event.count, name: event.involvedObject.name, kind: event.involvedObject.kind, subObject: event.involvedObject.fieldPath, reason: event.reason, source: _sources, message: event.message }); }); }).error($scope.handleError); } getData(); } ]); /**========================================================= * Module: Minions * Visualizer for minions =========================================================*/ app.controller('ListMinionsCtrl', [ '$scope', '$routeParams', 'k8sv1Beta3Api', '$location', function($scope, $routeParams, k8sApi, $location) { 'use strict'; $scope.getData = getData; $scope.loading = true; $scope.k8sApi = k8sApi; $scope.pods = null; $scope.groupedPods = null; $scope.serverView = false; $scope.headers = [{name: 'Name', field: 'name'}, {name: 'Addresses', field: 'addresses'}, {name: 'Status', field: 'status'}]; $scope.custom = { name: '', status: 'grey', ip: 'grey' }; $scope.sortable = ['name', 'status', 'ip']; $scope.thumbs = 'thumb'; $scope.count = 10; $scope.go = function(d) { $location.path('/dashboard/nodes/' + d.name); }; function handleError(data, status, headers, config) { console.log("Error (" + status + "): " + data); $scope.loading = false; } $scope.content = []; function getData() { $scope.loading = true; k8sApi.getMinions().success(function(data) { $scope.loading = false; var _fixComma = function(str) { if (str.substring(0, 1) == ',') { return str.substring(1); } else { return str; } }; data.items.forEach(function(minion) { var _statusType = ''; if (minion.status.conditions) { Object.keys(minion.status.conditions) .forEach(function(key) { _statusType += minion.status.conditions[key].type; }); } $scope.content.push({name: minion.metadata.name, addresses: _.map(minion.status.addresses, function(a) { return a.address }).join(', '), status: _statusType}); }); }).error($scope.handleError); } getData(); } ]); app.controller('ListPodsCtrl', [ '$scope', '$routeParams', 'k8sv1Beta3Api', 'lodash', '$location', function($scope, $routeParams, k8sApi, lodash, $location) { var _ = lodash; $scope.getData = getData; $scope.loading = true; $scope.k8sApi = k8sApi; $scope.pods = null; $scope.groupedPods = null; $scope.serverView = false; $scope.headers = [ {name: 'Pod', field: 'pod'}, {name: 'IP', field: 'ip'}, {name: 'Status', field: 'status'}, {name: 'Containers', field: 'containers'}, {name: 'Images', field: 'images'}, {name: 'Host', field: 'host'}, {name: 'Labels', field: 'labels'} ]; $scope.custom = { pod: '', ip: 'grey', containers: 'grey', images: 'grey', host: 'grey', labels: 'grey', status: 'grey' }; $scope.sortable = ['pod', 'ip', 'status']; $scope.count = 10; $scope.go = function(data) { $location.path('/dashboard/pods/' + data.pod); }; var orderedPodNames = []; function handleError(data, status, headers, config) { console.log("Error (" + status + "): " + data); $scope.loading = false; }; function getPodName(pod) { return _.has(pod.metadata.labels, 'name') ? pod.metadata.labels.name : pod.metadata.name; } $scope.content = []; function getData() { $scope.loading = true; k8sApi.getPods().success(angular.bind(this, function(data) { $scope.loading = false; var _fixComma = function(str) { if (str.substring(0, 1) == ',') { return str.substring(1); } else { return str; } }; data.items.forEach(function(pod) { var _containers = '', _images = '', _labels = '', _uses = ''; if (pod.spec) { Object.keys(pod.spec.containers) .forEach(function(key) { _containers += ', ' + pod.spec.containers[key].name; _images += ', ' + pod.spec.containers[key].image; }); } if (pod.metadata.labels) { Object.keys(pod.metadata.labels) .forEach(function(key) { if (key == 'name') { _labels += ', ' + pod.metadata.labels[key]; } if (key == 'uses') { _uses += ', ' + pod.metadata.labels[key]; } }); } $scope.content.push({ pod: pod.metadata.name, ip: pod.status.podIP, containers: _fixComma(_containers), images: _fixComma(_images), host: pod.spec.host, labels: _fixComma(_labels) + ':' + _fixComma(_uses), status: pod.status.phase }); }); })).error(angular.bind(this, handleError)); }; $scope.getPodRestarts = function(pod) { var r = null; var container = _.first(pod.spec.containers); if (container) r = pod.status.containerStatuses[container.name].restartCount; return r; }; $scope.otherLabels = function(labels) { return _.omit(labels, 'name') }; $scope.podStatusClass = function(pod) { var s = pod.status.phase.toLowerCase(); if (s == 'running' || s == 'succeeded') return null; else return "status-" + s; }; $scope.podIndexFromName = function(pod) { var name = getPodName(pod); return _.indexOf(orderedPodNames, name) + 1; }; getData(); } ]); /**========================================================= * Module: Replication Controllers * Visualizer for replication controllers =========================================================*/ app.controller('ListReplicationControllersCtrl', [ '$scope', '$routeParams', 'k8sApi', '$location', function($scope, $routeParams, k8sApi, $location) { 'use strict'; $scope.getData = getData; $scope.loading = true; $scope.k8sApi = k8sApi; $scope.pods = null; $scope.groupedPods = null; $scope.serverView = false; $scope.headers = [ {name: 'Controller', field: 'controller'}, {name: 'Containers', field: 'containers'}, {name: 'Images', field: 'images'}, {name: 'Selector', field: 'selector'}, {name: 'Replicas', field: 'replicas'} ]; $scope.custom = { controller: '', containers: 'grey', images: 'grey', selector: 'grey', replicas: 'grey' }; $scope.sortable = ['controller', 'containers', 'images']; $scope.thumbs = 'thumb'; $scope.count = 10; $scope.go = function(data) { $location.path('/dashboard/replicationcontrollers/' + data.controller); }; function handleError(data, status, headers, config) { console.log("Error (" + status + "): " + data); $scope.loading = false; } $scope.content = []; function getData() { $scope.loading = true; k8sApi.getReplicationControllers().success(function(data) { $scope.loading = false; var _fixComma = function(str) { if (str.substring(0, 1) == ',') { return str.substring(1); } else { return str; } }; data.items.forEach(function(replicationController) { var _name = '', _image = ''; if (replicationController.desiredState.podTemplate.desiredState.manifest.containers) { Object.keys(replicationController.desiredState.podTemplate.desiredState.manifest.containers) .forEach(function(key) { _name += replicationController.desiredState.podTemplate.desiredState.manifest.containers[key].name; _image += replicationController.desiredState.podTemplate.desiredState.manifest.containers[key].image; }); } var _name_selector = ''; if (replicationController.desiredState.replicaSelector) { Object.keys(replicationController.desiredState.replicaSelector) .forEach(function(key) { _name_selector += replicationController.desiredState.replicaSelector[key]; }); } $scope.content.push({ controller: replicationController.id, containers: _name, images: _image, selector: _name_selector, replicas: replicationController.currentState.replicas }); }); }).error($scope.handleError); } getData(); } ]); /**========================================================= * Module: Services * Visualizer for services =========================================================*/ app.controller('ListServicesCtrl', [ '$scope', '$interval', '$routeParams', 'k8sApi', '$rootScope', '$location', function($scope, $interval, $routeParams, k8sApi, $rootScope, $location) { 'use strict'; $scope.doTheBack = function() { window.history.back(); }; $scope.headers = [ {name: 'Name', field: 'name'}, {name: 'Labels', field: 'labels'}, {name: 'Selector', field: 'selector'}, {name: 'IP', field: 'ip'}, {name: 'Port', field: 'port'} ]; $scope.custom = { name: '', ip: 'grey', selector: 'grey', port: 'grey', labels: 'grey' }; $scope.sortable = ['name', 'ip', 'port']; $scope.count = 10; $scope.go = function(data) { $location.path('/dashboard/services/' + data.name); }; $scope.content = []; $rootScope.doTheBack = $scope.doTheBack; $scope.handleError = function(data, status, headers, config) { console.log("Error (" + status + "): " + data); $scope_.loading = false; }; $scope.getData = function() { $scope.loading = true; k8sApi.getServices().success(angular.bind(this, function(data) { $scope.services = data; $scope.loading = false; var _fixComma = function(str) { if (str.substring(0, 1) == ',') { return str.substring(1); } else { return str; } }; var addLabel = function(str, label) { if (str) { str = label + str; } return str; }; if (data.items.constructor === Array) { data.items.forEach(function(service) { var _name = '', _uses = '', _component = '', _provider = ''; if (service.labels !== null && typeof service.labels === 'object') { Object.keys(service.labels) .forEach(function(key) { if (key == 'name') { _name += ',' + service.labels[key]; } if (key == 'component') { _component += ',' + service.labels[key]; } if (key == 'provider') { _provider += ',' + service.labels[key]; } }); } var _selectors = ''; if (service.selector !== null && typeof service.selector === 'object') { Object.keys(service.selector) .forEach(function(key) { if (key == 'name') { _selectors += ',' + service.selector[key]; } }); } $scope.content.push({ name: service.id, ip: service.portalIP, port: service.port, selector: addLabel(_fixComma(_selectors), 'name='), labels: addLabel(_fixComma(_name), 'name=') + ' ' + addLabel(_fixComma(_component), 'component=') + ' ' + addLabel(_fixComma(_provider), 'provider=') }); }); } })).error($scope.handleError); }; $scope.getData(); } ]); /**========================================================= * Module: Nodes * Visualizer for nodes =========================================================*/ app.controller('NodeCtrl', [ '$scope', '$interval', '$routeParams', 'k8sv1Beta3Api', '$rootScope', function($scope, $interval, $routeParams, k8sApi, $rootScope) { 'use strict'; $scope.doTheBack = function() { window.history.back(); }; $rootScope.doTheBack = $scope.doTheBack; $scope.handleError = function(data, status, headers, config) { console.log("Error (" + status + "): " + data); $scope_.loading = false; }; $scope.handleNode = function(nodeId) { $scope.loading = true; k8sApi.getNodes(nodeId).success(angular.bind(this, function(data) { $scope.node = data; $scope.loading = false; })).error($scope.handleError); }; $scope.handleNode($routeParams.nodeId); } ]); /**========================================================= * Module: Pods * Visualizer for pods =========================================================*/ app.controller('PodCtrl', [ '$scope', '$interval', '$routeParams', 'k8sv1Beta3Api', '$rootScope', function($scope, $interval, $routeParams, k8sApi, $rootScope) { 'use strict'; $scope.doTheBack = function() { window.history.back(); }; $rootScope.doTheBack = $scope.doTheBack; $scope.handleError = function(data, status, headers, config) { console.log("Error (" + status + "): " + data); $scope_.loading = false; }; $scope.handlePod = function(podId) { $scope.loading = true; k8sApi.getPods(podId).success(angular.bind(this, function(data) { $scope.pod = data; $scope.loading = false; })).error($scope.handleError); }; $scope.handlePod($routeParams.podId); } ]); /**========================================================= * Module: Replication * Visualizer for replication controllers =========================================================*/ function ReplicationController() { } ReplicationController.prototype.getData = function(dataId) { this.scope.loading = true; this.k8sApi.getReplicationControllers(dataId).success(angular.bind(this, function(data) { this.scope.replicationController = data; this.scope.loading = false; })).error(angular.bind(this, this.handleError)); }; ReplicationController.prototype.handleError = function(data, status, headers, config) { console.log("Error (" + status + "): " + data); this.scope.loading = false; }; app.controller('ReplicationControllerCtrl', [ '$scope', '$routeParams', 'k8sApi', function($scope, $routeParams, k8sApi) { $scope.controller = new ReplicationController(); $scope.controller.k8sApi = k8sApi; $scope.controller.scope = $scope; $scope.controller.getData($routeParams.replicationControllerId); $scope.doTheBack = function() { window.history.back(); }; } ]); /**========================================================= * Module: Services * Visualizer for services =========================================================*/ function ServiceController() { } ServiceController.prototype.getData = function(dataId) { this.scope.loading = true; this.k8sApi.getServices(dataId).success(angular.bind(this, function(data) { this.scope.service = data; this.scope.loading = false; })).error(angular.bind(this, this.handleError)); }; ServiceController.prototype.handleError = function(data, status, headers, config) { console.log("Error (" + status + "): " + data); this.scope.loading = false; }; app.controller('ServiceCtrl', [ '$scope', '$routeParams', 'k8sApi', '$location', function($scope, $routeParams, k8sApi, $location) { $scope.controller = new ServiceController(); $scope.controller.k8sApi = k8sApi; $scope.controller.scope = $scope; $scope.controller.getData($routeParams.serviceId); $scope.doTheBack = function() { window.history.back(); }; } ]); (function() { 'use strict'; angular.module('kubernetesApp.components.dashboard') .directive('d3MinionBarGauge', [ 'd3DashboardService', function(d3DashboardService) { return { restrict: 'E', scope: { data: '=', thickness: '@', graphWidth: '@', graphHeight: '@' }, link: function(scope, element, attrs) { var draw = function(d3) { var svg = d3.select("svg.chart"); var legendSvg = d3.select("svg.legend"); window.onresize = function() { return scope.$apply(); }; scope.$watch(function() { return angular.element(window)[0].innerWidth; }, function() { return scope.render(scope.data); }); scope.$watch('data', function(newVals, oldVals) { return initOrUpdate(newVals, oldVals); }, true); function initOrUpdate(newVals, oldVals) { if (oldVals === null || oldVals === undefined) { return scope.render(newVals); } else { return update(oldVals, newVals); } } var textOffset = 10; var el = null; var radius = 100; var oldData = []; function init(options) { var clone = options.data; var preparedData = setData(clone); setup(preparedData, options.width, options.height); } function setup(data, w, h) { svg = d3.select(element[0]).append("svg").attr("width", "100%"); legendSvg = d3.select(element[0]).append("svg").attr("width", "100%"); var chart = svg.attr("class", "chart") .attr("width", w) .attr("height", h - 25) .append("svg:g") .attr("class", "concentricchart") .attr("transform", "translate(" + ((w / 2)) + "," + h / 4 + ")"); var legend = legendSvg.attr("class", "legend").attr("width", w); radius = Math.min(w, h) / 2; var hostName = legendSvg.append("text") .attr("class", "hostName") .attr("transform", "translate(" + ((w - 120) / 2) + "," + 15 + ")"); var label_legend_area = legendSvg.append("svg:g") .attr("class", "label_legend_area") .attr("transform", "translate(" + ((w - 185) / 2) + "," + 35 + ")"); var legend_group = label_legend_area.append("svg:g").attr("class", "legend_group"); var label_group = label_legend_area.append("svg:g") .attr("class", "label_group") .attr("transform", "translate(" + 25 + "," + 11 + ")"); var stats_group = label_legend_area.append("svg:g") .attr("class", "stats_group") .attr("transform", "translate(" + 85 + "," + 11 + ")"); var path_group = chart.append("svg:g") .attr("class", "path_group") .attr("transform", "translate(0," + (h / 4) + ")"); var value_group = chart.append("svg:g") .attr("class", "value_group") .attr("transform", "translate(" + -(w * 0.205) + "," + -(h * 0.10) + ")"); generateArcs(chart, data); } function update(_oldData, _newData) { if (_newData === undefined || _newData === null) { return; } var clone = jQuery.extend(true, {}, _newData); var cloneOld = jQuery.extend(true, {}, _oldData); var preparedData = setData(clone); oldData = setData(cloneOld); animate(preparedData); } function animate(data) { generateArcs(null, data); } function setData(data) { var diameter = 2 * Math.PI * radius; var localData = []; $.each(data[0].segments, function(ri, value) { function calcAngles(v) { var segmentValueSum = 200; if (v > segmentValueSum) { v = segmentValueSum; } var segmentValue = v; var fraction = segmentValue / segmentValueSum; var arcBatchLength = fraction * 4 * Math.PI; var arcPartition = arcBatchLength; var startAngle = Math.PI * 2; var endAngle = startAngle + arcPartition; return { startAngle: startAngle, endAngle: endAngle }; } var valueData = calcAngles(value.value); data[0].segments[ri].startAngle = valueData.startAngle; data[0].segments[ri].endAngle = valueData.endAngle; var maxData = value.maxData; var maxTickData = calcAngles(maxData.maxValue + 0.2); data[0].segments[ri].maxTickStartAngle = maxTickData.startAngle; data[0].segments[ri].maxTickEndAngle = maxTickData.endAngle; var maxArcData = calcAngles(maxData.maxValue); data[0].segments[ri].maxArcStartAngle = maxArcData.startAngle; data[0].segments[ri].maxArcEndAngle = maxArcData.endAngle; data[0].segments[ri].index = ri; }); localData.push(data[0].segments); return localData[0]; } function generateArcs(_svg, data) { var chart = svg; var transitionTime = 750; $.each(data, function(index, value) { if (oldData[index] !== undefined) { data[index].previousEndAngle = oldData[index].endAngle; } else { data[index].previousEndAngle = 0; } }); var thickness = parseInt(scope.thickness, 10); var ir = (parseInt(scope.graphWidth, 10) / 3); var path_group = svg.select('.path_group'); var arc_group = path_group.selectAll(".arc_group").data(data); var arcEnter = arc_group.enter().append("g").attr("class", "arc_group"); arcEnter.append("path").attr("class", "bg-circle").attr("d", getBackgroundArc(thickness, ir)); arcEnter.append("path") .attr("class", function(d, i) { return 'max_tick_arc ' + d.maxData.maxTickClassNames; }); arcEnter.append("path") .attr("class", function(d, i) { return 'max_bg_arc ' + d.maxData.maxClassNames; }); arcEnter.append("path").attr("class", function(d, i) { return 'value_arc ' + d.classNames; }); var max_tick_arc = arc_group.select(".max_tick_arc"); max_tick_arc.transition() .attr("class", function(d, i) { return 'max_tick_arc ' + d.maxData.maxTickClassNames; }) .attr("d", function(d) { var arc = maxArc(thickness, ir); arc.startAngle(d.maxTickStartAngle); arc.endAngle(d.maxTickEndAngle); return arc(d); }); var max_bg_arc = arc_group.select(".max_bg_arc"); max_bg_arc.transition() .attr("class", function(d, i) { return 'max_bg_arc ' + d.maxData.maxClassNames; }) .attr("d", function(d) { var arc = maxArc(thickness, ir); arc.startAngle(d.maxArcStartAngle); arc.endAngle(d.maxArcEndAngle); return arc(d); }); var value_arc = arc_group.select(".value_arc"); value_arc.transition().ease("exp").attr("class", function(d, i) { return 'value_arc ' + d.classNames; }).duration(transitionTime).attrTween("d", function(d) { return arcTween(d, thickness, ir); }); arc_group.exit() .select(".value_arc") .transition() .ease("exp") .duration(transitionTime) .attrTween("d", function(d) { return arcTween(d, thickness, ir); }) .remove(); drawLabels(chart, data, ir, thickness); buildLegend(chart, data); } function arcTween(b, thickness, ir) { var prev = JSON.parse(JSON.stringify(b)); prev.endAngle = b.previousEndAngle; var i = d3.interpolate(prev, b); return function(t) { return getArc(thickness, ir)(i(t)); }; } function maxArc(thickness, ir) { var arc = d3.svg.arc().innerRadius(function(d) { return getRadiusRing(ir, d.index); }).outerRadius(function(d) { return getRadiusRing(ir + thickness, d.index); }); return arc; } function drawLabels(chart, data, ir, thickness) { svg.select('.value_group').selectAll("*").remove(); var counts = data.length; var value_group = chart.select('.value_group'); var valueLabels = value_group.selectAll("text.value").data(data); valueLabels.enter() .append("svg:text") .attr("class", "value") .attr( "transform", function(d) { return "translate(" + (getRadiusRing(ir, counts - 1)) + ", 0)"; }) .attr("dx", function(d, i) { return 0; }) .attr("dy", function(d, i) { return (thickness + 3) * i; }) .attr("text-anchor", function(d) { return "start"; }) .text(function(d) { return d.value; }); valueLabels.transition().duration(300).attrTween( "d", function(d) { return arcTween(d, thickness, ir); }); valueLabels.exit().remove(); } function buildLegend(chart, data) { var svg = legendSvg; svg.select('.label_group').selectAll("*").remove(); svg.select('.legend_group').selectAll("*").remove(); svg.select('.stats_group').selectAll("*").remove(); var host_name = svg.select('.hostName'); var label_group = svg.select('.label_group'); var stats_group = svg.select('.stats_group'); host_name.text(data[0].hostName); host_name = svg.selectAll("text.hostName").data(data); host_name.attr("text-anchor", function(d) { return "start"; }) .text(function(d) { return d.hostName; }); host_name.exit().remove(); var labels = label_group.selectAll("text.labels").data(data); labels.enter() .append("svg:text") .attr("class", "labels") .attr("dy", function(d, i) { return 19 * i; }) .attr("text-anchor", function(d) { return "start"; }) .text(function(d) { return d.label; }); labels.exit().remove(); var stats = stats_group.selectAll("text.stats").data(data); stats.enter() .append("svg:text") .attr("class", "stats") .attr("dy", function(d, i) { return 19 * i; }) .attr("text-anchor", function(d) { return "start"; }) .text(function(d) { return d.stats; }); stats.exit().remove(); var legend_group = svg.select('.legend_group'); var legend = legend_group.selectAll("rect").data(data); legend.enter() .append("svg:rect") .attr("x", 2) .attr("y", function(d, i) { return 19 * i; }) .attr("width", 13) .attr("height", 13) .attr("class", function(d, i) { return "rect " + d.classNames; }); legend.exit().remove(); } function getRadiusRing(ir, i) { return ir - (i * 20); } function getArc(thickness, ir) { var arc = d3.svg.arc() .innerRadius(function(d) { return getRadiusRing(ir, d.index); }) .outerRadius(function(d) { return getRadiusRing(ir + thickness, d.index); }) .startAngle(function(d, i) { return d.startAngle; }) .endAngle(function(d, i) { return d.endAngle; }); return arc; } function getBackgroundArc(thickness, ir) { var arc = d3.svg.arc() .innerRadius(function(d) { return getRadiusRing(ir, d.index); }) .outerRadius(function(d) { return getRadiusRing(ir + thickness, d.index); }) .startAngle(0) .endAngle(function() { return 2 * Math.PI; }); return arc; } scope.render = function(data) { if (data === undefined || data === null) { return; } svg.selectAll("*").remove(); var graph = $(element[0]); var w = scope.graphWidth; var h = scope.graphHeight; var options = { data: data, width: w, height: h }; init(options); }; }; d3DashboardService.d3().then(draw); } }; } ]); }()); (function() { 'use strict'; angular.module('kubernetesApp.components.dashboard') .directive( 'dashboardHeader', function() { 'use strict'; return { restrict: 'A', replace: true, scope: {user: '='}, templateUrl: "components/dashboard/pages/header.html", controller: [ '$scope', '$filter', '$location', 'menu', '$rootScope', function($scope, $filter, $location, menu, $rootScope) { $scope.menu = menu; $scope.$watch('page', function(newValue, oldValue) { if (typeof newValue !== 'undefined') { $location.path(newValue); } }); $scope.subpages = [ { category: 'dashboard', name: 'Explore', value: '/dashboard/groups/type/selector/', id: 'groupsView' }, {category: 'dashboard', name: 'Pods', value: '/dashboard/pods', id: 'podsView'}, {category: 'dashboard', name: 'Nodes', value: '/dashboard/nodes', id: 'minionsView'}, { category: 'dashboard', name: 'Replication Controllers', value: '/dashboard/replicationcontrollers', id: 'rcView' }, {category: 'dashboard', name: 'Services', value: '/dashboard/services', id: 'servicesView'}, {category: 'dashboard', name: 'Events', value: '/dashboard/events', id: 'eventsView'}, ]; } ] }; }) .directive('dashboardFooter', function() { 'use strict'; return { restrict: 'A', replace: true, templateUrl: "components/dashboard/pages/footer.html", controller: ['$scope', '$filter', function($scope, $filter) {}] }; }) .directive('mdTable', function() { 'use strict'; return { restrict: 'E', scope: { headers: '=', content: '=', sortable: '=', filters: '=', customClass: '=customClass', thumbs: '=', count: '=', doSelect: '&onSelect' }, transclude: true, controller: ["$scope", "$filter", "$window", "$location", function($scope, $filter, $window, $location) { var orderBy = $filter('orderBy'); $scope.currentPage = 0; $scope.nbOfPages = function() { return Math.ceil($scope.content.length / $scope.count); }; $scope.handleSort = function(field) { if ($scope.sortable.indexOf(field) > -1) { return true; } else { return false; } }; $scope.order = function(predicate, reverse) { $scope.content = orderBy($scope.content, predicate, reverse); $scope.predicate = predicate; }; $scope.order($scope.sortable[0], false); $scope.getNumber = function(num) { return new Array(num); }; $scope.goToPage = function(page) { $scope.currentPage = page; }; $scope.showMore = function() { return angular.isDefined($scope.moreClick);} }], templateUrl: 'views/partials/md-table.tmpl.html' }; }); }()); angular.module('kubernetesApp.components.dashboard') .factory('d3DashboardService', [ '$document', '$q', '$rootScope', function($document, $q, $rootScope) { var d = $q.defer(); function onScriptLoad() { // Load client in the browser $rootScope.$apply(function() { d.resolve(window.d3); }); } // Create a script tag with d3 as the source // and call our onScriptLoad callback when it // has been loaded var scriptTag = $document[0].createElement('script'); scriptTag.type = 'text/javascript'; scriptTag.async = true; scriptTag.src = 'vendor/d3/d3.min.js'; scriptTag.onreadystatechange = function() { if (this.readyState == 'complete') onScriptLoad(); }; scriptTag.onload = onScriptLoad; var s = $document[0].getElementsByTagName('body')[0]; s.appendChild(scriptTag); return { d3: function() { return d.promise; } }; } ]); (function() { 'use strict'; angular.module('pods', []).service('podService', PodDataService); /** * Pod DataService * Mock async data service. * * @returns {{loadAll: Function}} * @constructor */ function PodDataService($q) { var pods = { "kind": "Pod", "apiVersion": "v1beta3", "metadata": { "name": "redis-master-c0r1n", "generateName": "redis-master-", "namespace": "default", "selfLink": "/api/v1beta3/namespaces/default/pods/redis-master-c0r1n", "uid": "f12ddfaf-ff77-11e4-8f2d-080027213276", "resourceVersion": "39", "creationTimestamp": "2015-05-21T05:12:14Z", "labels": { "name": "redis-master" }, "annotations": { "kubernetes.io/created-by": "{\"kind\":\"SerializedReference\",\"apiVersion\":\"v1beta3\",\"reference\":{\"kind\":\"ReplicationController\",\"namespace\":\"default\",\"name\":\"redis-master\",\"uid\":\"f12969e0-ff77-11e4-8f2d-080027213276\",\"apiVersion\":\"v1beta3\",\"resourceVersion\":\"26\"}}" } }, "spec": { "volumes": [ { "name": "default-token-zb4rq", "secret": { "secretName": "default-token-zb4rq" } } ], "containers": [ { "name": "master", "image": "redis", "ports": [ { "containerPort": 6379, "protocol": "TCP" } ], "resources": {}, "volumeMounts": [ { "name": "default-token-zb4rq", "readOnly": true, "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount" } ], "terminationMessagePath": "/dev/termination-log", "imagePullPolicy": "IfNotPresent", "capabilities": {}, "securityContext": { "capabilities": {}, "privileged": false } } ], "restartPolicy": "Always", "dnsPolicy": "ClusterFirst", "serviceAccount": "default", "host": "127.0.0.1" }, "status": { "phase": "Running", "Condition": [ { "type": "Ready", "status": "True" } ], "hostIP": "127.0.0.1", "podIP": "172.17.0.1", "startTime": "2015-05-21T05:12:14Z", "containerStatuses": [ { "name": "master", "state": { "running": { "startedAt": "2015-05-21T05:12:14Z" } }, "lastState": {}, "ready": true, "restartCount": 0, "image": "redis", "imageID": "docker://95af5842ddb9b03f7c6ec7601e65924cec516fcedd7e590ae31660057085cf67", "containerID": "docker://ae2a1e0a91a8b1015191a0b8e2ce8c55a86fb1a9a2b1e8e3b29430c9d93c8c09" } ] } }; // Uses promises return { loadAll: function() { // Simulate async call return $q.when(pods); } }; } PodDataService.$inject = ["$q"]; })(); (function() { 'use strict'; angular.module('replicationControllers', []) .service('replicationControllerService', ReplicationControllerDataService); /** * Replication Controller DataService * Mock async data service. * * @returns {{loadAll: Function}} * @constructor */ function ReplicationControllerDataService($q) { var replicationControllers = { "kind": "List", "apiVersion": "v1beta3", "metadata": {}, "items": [ { "kind": "ReplicationController", "apiVersion": "v1beta3", "metadata": { "name": "redis-master", "namespace": "default", "selfLink": "/api/v1beta3/namespaces/default/replicationcontrollers/redis-master", "uid": "f12969e0-ff77-11e4-8f2d-080027213276", "resourceVersion": "28", "creationTimestamp": "2015-05-21T05:12:14Z", "labels": { "name": "redis-master" } }, "spec": { "replicas": 1, "selector": { "name": "redis-master" }, "template": { "metadata": { "creationTimestamp": null, "labels": { "name": "redis-master" } }, "spec": { "containers": [ { "name": "master", "image": "redis", "ports": [ { "containerPort": 6379, "protocol": "TCP" } ], "resources": {}, "terminationMessagePath": "/dev/termination-log", "imagePullPolicy": "IfNotPresent", "capabilities": {}, "securityContext": { "capabilities": {}, "privileged": false } } ], "restartPolicy": "Always", "dnsPolicy": "ClusterFirst", "serviceAccount": "" } } }, "status": { "replicas": 1 } } ]}; // Uses promises return { loadAll: function() { // Simulate async call return $q.when(replicationControllers); } }; } ReplicationControllerDataService.$inject = ["$q"]; })(); (function() { 'use strict'; angular.module('services', []).service('serviceService', ServiceDataService); /** * Service DataService * Mock async data service. * * @returns {{loadAll: Function}} * @constructor */ function ServiceDataService($q) { var services = { "kind": "List", "apiVersion": "v1beta3", "metadata": {}, "items": [ { "kind": "Service", "apiVersion": "v1beta3", "metadata": { "name": "kubernetes", "namespace": "default", "selfLink": "/api/v1beta3/namespaces/default/services/kubernetes", "resourceVersion": "6", "creationTimestamp": null, "labels": { "component": "apiserver", "provider": "kubernetes" } }, "spec": { "ports": [ { "protocol": "TCP", "port": 443, "targetPort": 443 } ], "portalIP": "10.0.0.2", "sessionAffinity": "None" }, "status": {} }, { "kind": "Service", "apiVersion": "v1beta3", "metadata": { "name": "kubernetes-ro", "namespace": "default", "selfLink": "/api/v1beta3/namespaces/default/services/kubernetes-ro", "resourceVersion": "8", "creationTimestamp": null, "labels": { "component": "apiserver", "provider": "kubernetes" } }, "spec": { "ports": [ { "protocol": "TCP", "port": 80, "targetPort": 80 } ], "portalIP": "10.0.0.1", "sessionAffinity": "None" }, "status": {} }, { "kind": "Service", "apiVersion": "v1beta3", "metadata": { "name": "redis-master", "namespace": "default", "selfLink": "/api/v1beta3/namespaces/default/services/redis-master", "uid": "a6fde246-ff78-11e4-8f2d-080027213276", "resourceVersion": "72", "creationTimestamp": "2015-05-21T05:17:19Z", "labels": { "name": "redis-master" } }, "spec": { "ports": [ { "protocol": "TCP", "port": 6379, "targetPort": 6379 } ], "selector": { "name": "redis-master" }, "portalIP": "10.0.0.124", "sessionAffinity": "None" }, "status": {} } ] }; // Uses promises return { loadAll: function() { // Simulate async call return $q.when(services); } }; } ServiceDataService.$inject = ["$q"]; })(); `) func www_app_assets_js_app_js_bytes() ([]byte, error) { return _www_app_assets_js_app_js, nil } func www_app_assets_js_app_js() (*asset, error) { bytes, err := www_app_assets_js_app_js_bytes() if err != nil { return nil, err } info := bindata_file_info{name: "www/app/assets/js/app.js", size: 93554, mode: os.FileMode(420), modTime: time.Unix(1432768978, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _www_app_assets_js_base_js = []byte(`!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){function n(e){var t=e.length,n=Z.type(e);return"function"===n||Z.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e}function r(e,t,n){if(Z.isFunction(t))return Z.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return Z.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(ae.test(t))return Z.filter(t,e,n);t=Z.filter(t,e)}return Z.grep(e,function(e){return U.call(t,e)>=0!==n})}function i(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}function o(e){var t=he[e]={};return Z.each(e.match(de)||[],function(e,n){t[n]=!0}),t}function s(){J.removeEventListener("DOMContentLoaded",s,!1),e.removeEventListener("load",s,!1),Z.ready()}function a(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=Z.expando+a.uid++}function u(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(be,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:xe.test(n)?Z.parseJSON(n):n}catch(i){}ye.set(e,t,n)}else n=void 0;return n}function l(){return!0}function c(){return!1}function f(){try{return J.activeElement}catch(e){}}function p(e,t){return Z.nodeName(e,"table")&&Z.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function d(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function h(e){var t=Pe.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function g(e,t){for(var n=0,r=e.length;r>n;n++)ve.set(e[n],"globalEval",!t||ve.get(t[n],"globalEval"))}function m(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(ve.hasData(e)&&(o=ve.access(e),s=ve.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)Z.event.add(t,i,l[i][n])}ye.hasData(e)&&(a=ye.access(e),u=Z.extend({},a),ye.set(t,u))}}function v(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return void 0===t||t&&Z.nodeName(e,t)?Z.merge([e],n):n}function y(e,t){var n=t.nodeName.toLowerCase();"input"===n&&Ne.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}function x(t,n){var r,i=Z(n.createElement(t)).appendTo(n.body),o=e.getDefaultComputedStyle&&(r=e.getDefaultComputedStyle(i[0]))?r.display:Z.css(i[0],"display");return i.detach(),o}function b(e){var t=J,n=$e[e];return n||(n=x(e,t),"none"!==n&&n||(We=(We||Z("