feat: [ui] Relative navigation; add storageClass (#1835)

- Change all ui request from absolute path to relative path.
  Can access ui web like ex.com/pgo/ with nginx spec config
  relative issue: zalando#1613

- Add storageClass field relative-nav

Co-authored-by: Felix Kunde <felix-kunde@gmx.de>
This commit is contained in:
chengyou tang 2022-12-29 22:22:22 +08:00 committed by GitHub
parent e80cccb93b
commit 2011367525
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 93 additions and 70 deletions

View File

@ -214,13 +214,13 @@ const delete_cluster = (namespace, clustername) => {
jQuery.ajax({ jQuery.ajax({
type: 'DELETE', type: 'DELETE',
url: ( url: (
'/postgresqls/' './postgresqls/'
+ encodeURI(namespace) + encodeURI(namespace)
+ '/' + encodeURI(clustername) + '/' + encodeURI(clustername)
), ),
dataType: 'text', dataType: 'text',
success: () => location.assign('/#/list'), success: () => location.assign('./#/list'),
error: (r, status, error) => location.assign('/#/list'), // TODO: show error error: (r, status, error) => location.assign('./#/list'), // TODO: show error
}) })
}, },
}, },

View File

@ -4,23 +4,23 @@ app
.container .container
.navbar-header .navbar-header
a.navbar-brand(href='/') a.navbar-brand(href='./')
| PostgreSQL Operator UI | PostgreSQL Operator UI
#navbar.navbar-collapse.collapse #navbar.navbar-collapse.collapse
ul.nav.navbar-nav ul.nav.navbar-nav
li(class='{ active: ["EDIT", "LIST", "LOGS", "STATUS"].includes(activenav) }') li(class='{ active: ["EDIT", "LIST", "LOGS", "STATUS"].includes(activenav) }')
a(href='/#/list') PostgreSQL clusters a(href='./#/list') PostgreSQL clusters
li(class='{ active: "BACKUPS" === activenav }') li(class='{ active: "BACKUPS" === activenav }')
a(href='/#/backups') Backups a(href='./#/backups') Backups
li(class='{ active: "OPERATOR" === activenav }') li(class='{ active: "OPERATOR" === activenav }')
a(href='/#/operator') Status a(href='./#/operator') Status
li(class='{ active: "NEW" === activenav }') li(class='{ active: "NEW" === activenav }')
a(href='/#/new') New cluster a(href='./#/new') New cluster
li(if='{ config }') li(if='{ config }')
a(href='{ config.docs_link }' target='_blank') Documentation a(href='{ config.docs_link }' target='_blank') Documentation
@ -55,7 +55,7 @@ app
| |
| or | or
| |
a(href="/") start over a(href="./") start over
| . | .
div(if='{ config }') div(if='{ config }')
@ -152,12 +152,12 @@ app
;( ;(
jQuery jQuery
.get('/config') .get('./config')
.done(config => { .done(config => {
this.config = config this.config = config
;( ;(
jQuery jQuery
.get('/teams') .get('./teams')
.done(teams => { .done(teams => {
this.teams = teams.sort() this.teams = teams.sort()
this.team = this.teams[0] this.team = this.teams[0]

View File

@ -6,18 +6,18 @@ edit
ol.breadcrumb ol.breadcrumb
li.breadcrumb-item li.breadcrumb-item
a(href='/#/list') a(href='./#/list')
| PostgreSQL clusters | PostgreSQL clusters
li.breadcrumb-item(if='{ cluster_path }') li.breadcrumb-item(if='{ cluster_path }')
a(href='/#/status/{ cluster_path }') a(href='./#/status/{ cluster_path }')
| { qname } | { qname }
li.breadcrumb-item.active( li.breadcrumb-item.active(
aria-current='page' aria-current='page'
if='{ cluster_path }' if='{ cluster_path }'
) )
a(href='/#/edit/{ cluster_path }') a(href='./#/edit/{ cluster_path }')
| Edit | Edit
.row(if='{ cluster_path }') .row(if='{ cluster_path }')
@ -92,7 +92,7 @@ edit
jQuery.ajax({ jQuery.ajax({
type: 'POST', type: 'POST',
url: '/postgresqls/' + this.cluster_path, url: './postgresqls/' + this.cluster_path,
contentType:"application/json", contentType:"application/json",
data: jsonPayload, data: jsonPayload,
processData: false, processData: false,
@ -113,7 +113,7 @@ edit
this.pollProgress = () => { this.pollProgress = () => {
jQuery.get( jQuery.get(
'/postgresqls/' + this.cluster_path, './postgresqls/' + this.cluster_path,
).then(data => { ).then(data => {
// Input data: // Input data:
@ -148,6 +148,9 @@ edit
throughput: i.spec.volume.throughput || 125, throughput: i.spec.volume.throughput || 125,
iops: i.spec.volume.iops || 3000 iops: i.spec.volume.iops || 3000
} }
if ('storageClass' in i.spec.volume) {
o.spec.volume.storageClass=i.spec.volume.storageClass
}
o.spec.postgresql = {} o.spec.postgresql = {}
o.spec.postgresql.version = i.spec.postgresql.version o.spec.postgresql.version = i.spec.postgresql.version

View File

@ -5,15 +5,15 @@ logs
ol.breadcrumb ol.breadcrumb
li.breadcrumb-item li.breadcrumb-item
a(href='/#/list') a(href='./#/list')
| PostgreSQL clusters | PostgreSQL clusters
li.breadcrumb-item li.breadcrumb-item
a(href='/#/status/{ cluster_path }') a(href='./#/status/{ cluster_path }')
| { qname } | { qname }
li.breadcrumb-item li.breadcrumb-item
a(href='/#/logs/{ cluster_path }') a(href='./#/logs/{ cluster_path }')
| Logs | Logs
.sk-spinner-pulse(if='{ logs === undefined }') .sk-spinner-pulse(if='{ logs === undefined }')
@ -26,7 +26,7 @@ logs
| |
| or | or
| |
a(href="/") start over a(href="./") start over
| . | .
.container-fluid(if='{ logs }') .container-fluid(if='{ logs }')
@ -72,7 +72,7 @@ logs
) )
;( ;(
jQuery jQuery
.get(`/operator/clusters/${cluster_path}/logs`) .get(`./operator/clusters/${cluster_path}/logs`)
.done(logs => this.logs = logs.reverse()) .done(logs => this.logs = logs.reverse())
.fail(() => this.logs = null) .fail(() => this.logs = null)
.always(() => this.update()) .always(() => this.update())

View File

@ -18,7 +18,7 @@ new
ol.breadcrumb ol.breadcrumb
li.breadcrumb-item li.breadcrumb-item
a(href='/#/new') a(href='./#/new')
| New PostgreSQL cluster | New PostgreSQL cluster
.row.text-center(if='{ !creating }') .row.text-center(if='{ !creating }')
@ -64,7 +64,7 @@ new
a.btn.btn-small.btn-warning( a.btn.btn-small.btn-warning(
if='{ clusterExists }' if='{ clusterExists }'
href='/#/status/{ namespace.state }/{ name }' href='./#/status/{ namespace.state }/{ name }'
) )
| Cluster exists (show status) | Cluster exists (show status)
@ -299,6 +299,19 @@ new
) )
.input-group-addon .input-group-addon
.input-units Gi .input-units Gi
tr
td storageClass
td
.input-group
input.form-control(
ref='volumeStorageClass'
type='text'
value='{ volumeStorageClass }'
onchange='{ storageClassChange }'
onkeyup='{ storageClassChange }'
)
tr tr
td td
td Specify Iops and Throughput only if you need more than the default 3000 Iops and 125Mb/s EBS provides. td Specify Iops and Throughput only if you need more than the default 3000 Iops and 125Mb/s EBS provides.
@ -582,7 +595,8 @@ new
enableReplicaPoolerLoadBalancer: true enableReplicaPoolerLoadBalancer: true
{{/if}} {{/if}}
volume: volume:
size: "{{ volumeSize }}Gi"{{#if iops}} size: "{{ volumeSize }}Gi"{{#if volumeStorageClass}}
storageClass: "{{ volumeStorageClass }}"{{/if}}{{#if iops}}
iops: {{ iops }}{{/if}}{{#if throughput}} iops: {{ iops }}{{/if}}{{#if throughput}}
throughput: {{ throughput }}{{/if}} throughput: {{ throughput }}{{/if}}
{{#if users}} {{#if users}}
@ -638,6 +652,7 @@ new
enableMasterPoolerLoadBalancer: this.enableMasterPoolerLoadBalancer, enableMasterPoolerLoadBalancer: this.enableMasterPoolerLoadBalancer,
enableReplicaPoolerLoadBalancer: this.enableReplicaPoolerLoadBalancer, enableReplicaPoolerLoadBalancer: this.enableReplicaPoolerLoadBalancer,
volumeSize: this.volumeSize, volumeSize: this.volumeSize,
volumeStorageClass: this.volumeStorageClass,
iops: this.iops, iops: this.iops,
throughput: this.throughput, throughput: this.throughput,
users: this.users.valids, users: this.users.valids,
@ -716,6 +731,10 @@ new
this.volumeSize = +e.target.value this.volumeSize = +e.target.value
} }
this.storageClassChange = e => {
this.volumeStorageClass = e.target.value
}
this.iopsChange = e => { this.iopsChange = e => {
this.iops = +e.target.value this.iops = +e.target.value
} }
@ -759,7 +778,7 @@ new
this.checkClusterExists = () => ( this.checkClusterExists = () => (
jQuery jQuery
.get( .get(
'/postgresqls/' './postgresqls/'
+ this.namespace.state + this.namespace.state
+ '/' + '/'
+ this.clusterName + this.clusterName
@ -781,7 +800,7 @@ new
jQuery.ajax({ jQuery.ajax({
type: 'POST', type: 'POST',
url: '/create-cluster', url: './create-cluster',
contentType:'application/json', contentType:'application/json',
data: jsonPayload, data: jsonPayload,
processData: false, processData: false,
@ -1013,6 +1032,7 @@ new
this.clusterName = (this.name + '-').toLowerCase() this.clusterName = (this.name + '-').toLowerCase()
this.volumeSize = 10 this.volumeSize = 10
this.volumeStorageClass = ''
this.instanceCount = 1 this.instanceCount = 1
this.ranges = {} this.ranges = {}
this.odd = '' this.odd = ''

View File

@ -6,11 +6,11 @@ postgresql
ol.breadcrumb ol.breadcrumb
li.breadcrumb-item li.breadcrumb-item
a(href='/#/list') a(href='./#/list')
| PostgreSQL clusters | PostgreSQL clusters
li.breadcrumb-item(if='{ cluster_path }') li.breadcrumb-item(if='{ cluster_path }')
a(href='/#/status/{ cluster_path }') a(href='./#/status/{ cluster_path }')
| { qname } | { qname }
.row(if='{ cluster_path }') .row(if='{ cluster_path }')
@ -39,20 +39,20 @@ postgresql
) )
a.btn.btn-info( a.btn.btn-info(
href='/#/logs/{ cluster_path }' href='./#/logs/{ cluster_path }'
) )
| Logs | Logs
a.btn( a.btn(
class='btn-{ opts.read_write ? "primary" : "info" }' class='btn-{ opts.read_write ? "primary" : "info" }'
if='{ progress.postgresql }' if='{ progress.postgresql }'
href='/#/clone/{ clustername }/{ uid }/{ encodeURI(new Date().toISOString()) }' href='./#/clone/{ clustername }/{ uid }/{ encodeURI(new Date().toISOString()) }'
) )
| Clone | Clone
a.btn( a.btn(
class='btn-{ opts.read_write ? "warning" : "info" }' class='btn-{ opts.read_write ? "warning" : "info" }'
href='/#/edit/{ cluster_path }' href='./#/edit/{ cluster_path }'
) )
| Edit | Edit
@ -124,7 +124,7 @@ postgresql
this.pollProgress = () => { this.pollProgress = () => {
jQuery.get( jQuery.get(
'/postgresqls/' + this.cluster_path, './postgresqls/' + this.cluster_path,
).done(data => { ).done(data => {
this.progress.pooler = false this.progress.pooler = false
this.progress.postgresql = true this.progress.postgresql = true
@ -137,13 +137,13 @@ postgresql
this.update() this.update()
jQuery.get( jQuery.get(
'/statefulsets/' + this.cluster_path, './statefulsets/' + this.cluster_path,
).done(data => { ).done(data => {
this.progress.statefulSet = true this.progress.statefulSet = true
this.update() this.update()
jQuery.get( jQuery.get(
'/statefulsets/' + this.cluster_path + '/pods', './statefulsets/' + this.cluster_path + '/pods',
).done(data => { ).done(data => {
if (data.length > 0) { if (data.length > 0) {
this.progress.containerFirst = true this.progress.containerFirst = true
@ -157,7 +157,7 @@ postgresql
this.update() this.update()
jQuery.get( jQuery.get(
'/services/' + this.cluster_path, './services/' + this.cluster_path,
).done(data => { ).done(data => {
if (data.metadata && data.metadata.annotations && 'zalando.org/dnsname' in data.metadata.annotations) { if (data.metadata && data.metadata.annotations && 'zalando.org/dnsname' in data.metadata.annotations) {
this.progress.dnsName = data.metadata.annotations['zalando.org/dnsname'] this.progress.dnsName = data.metadata.annotations['zalando.org/dnsname']
@ -169,7 +169,7 @@ postgresql
} }
if (this.progress.poolerEnabled == true) { if (this.progress.poolerEnabled == true) {
jQuery.get('/pooler/' + this.cluster_path).done(data => { jQuery.get('./pooler/' + this.cluster_path).done(data => {
this.progress.pooler = {"url": ""} this.progress.pooler = {"url": ""}
this.update() this.update()
}) })

View File

@ -6,7 +6,7 @@ postgresqls
ol.breadcrumb ol.breadcrumb
li.breadcrumb-item li.breadcrumb-item
a(href='/#/list') a(href='./#/list')
| PostgreSQL clusters | PostgreSQL clusters
.sk-spinner-pulse( .sk-spinner-pulse(
@ -20,7 +20,7 @@ postgresqls
| |
| or | or
| |
a(href='/') start over a(href='./') start over
| . | .
div( div(
@ -81,7 +81,7 @@ postgresqls
td(style='white-space: pre') td(style='white-space: pre')
| { namespace } | { namespace }
td td
a(href='/#/status/{ cluster_path(this) }') { name } a(href='./#/status/{ cluster_path(this) }') { name }
btn.btn-danger(if='{status.PostgresClusterStatus == "CreateFailed"}') Create Failed btn.btn-danger(if='{status.PostgresClusterStatus == "CreateFailed"}') Create Failed
td { nodes } td { nodes }
td { cpu } / { cpu_limit } td { cpu } / { cpu_limit }
@ -101,7 +101,7 @@ postgresqls
) )
a.btn.btn-info( a.btn.btn-info(
href='/#/status/{ cluster_path(this) }' href='./#/status/{ cluster_path(this) }'
) )
i.fa.fa-check-circle.regular i.fa.fa-check-circle.regular
| Status | Status
@ -114,21 +114,21 @@ postgresqls
| Pgview | Pgview
a.btn.btn-info( a.btn.btn-info(
href='/#/logs/{ cluster_path(this) }' href='./#/logs/{ cluster_path(this) }'
) )
i.fa.fa-align-justify i.fa.fa-align-justify
| Logs | Logs
a.btn( a.btn(
class='btn-{ opts.read_write ? "primary" : "info" }' class='btn-{ opts.read_write ? "primary" : "info" }'
href='/#/clone/{ encodeURI(name) }/{ encodeURI(uid) }/{ encodeURI(new Date().toISOString()) }' href='./#/clone/{ encodeURI(name) }/{ encodeURI(uid) }/{ encodeURI(new Date().toISOString()) }'
) )
i.fa.fa-clone.regular i.fa.fa-clone.regular
| Clone | Clone
a.btn( a.btn(
class='btn-{ opts.read_write ? "warning" : "info" }' class='btn-{ opts.read_write ? "warning" : "info" }'
href='/#/edit/{ cluster_path(this) }' href='./#/edit/{ cluster_path(this) }'
) )
| Edit | Edit
@ -183,7 +183,7 @@ postgresqls
| { namespace } | { namespace }
td td
a( a(
href='/#/status/{ cluster_path(this) }' href='./#/status/{ cluster_path(this) }'
) )
| { name } | { name }
td { nodes } td { nodes }
@ -203,7 +203,7 @@ postgresqls
) )
a.btn.btn-info( a.btn.btn-info(
href='/#/status/{ cluster_path(this) }' href='./#/status/{ cluster_path(this) }'
) )
i.fa.fa-check-circle.regular i.fa.fa-check-circle.regular
| Status | Status
@ -217,21 +217,21 @@ postgresqls
| Pgview | Pgview
a.btn.btn-info( a.btn.btn-info(
href='/#/logs/{ cluster_path(this) }' href='./#/logs/{ cluster_path(this) }'
) )
i.fa.fa-align-justify i.fa.fa-align-justify
| Logs | Logs
a.btn( a.btn(
class='btn-{ opts.read_write ? "primary" : "info" }' class='btn-{ opts.read_write ? "primary" : "info" }'
href='/#/clone/{ encodeURI(name) }/{ encodeURI(uid) }/{ encodeURI(new Date().toISOString()) }' href='./#/clone/{ encodeURI(name) }/{ encodeURI(uid) }/{ encodeURI(new Date().toISOString()) }'
) )
i.fa.fa-clone.regular i.fa.fa-clone.regular
| Clone | Clone
a.btn( a.btn(
class='btn-{ opts.read_write ? "warning" : "info" }' class='btn-{ opts.read_write ? "warning" : "info" }'
href='/#/edit/{ cluster_path(this) }' href='./#/edit/{ cluster_path(this) }'
) )
| Edit | Edit
@ -343,7 +343,7 @@ postgresqls
this.on('mount', () => this.on('mount', () =>
jQuery jQuery
.get('/postgresqls') .get('./postgresqls')
.done(clusters => { .done(clusters => {
this.my_clusters = [] this.my_clusters = []
this.other_clusters = [] this.other_clusters = []

View File

@ -10,7 +10,7 @@ restore
| |
| or | or
| |
a(href="/") start over a(href="./") start over
| . | .
p(if='{ stored_clusters && stored_clusters.length === 0 }') p(if='{ stored_clusters && stored_clusters.length === 0 }')
@ -23,7 +23,7 @@ restore
ol.breadcrumb ol.breadcrumb
li.breadcrumb-item li.breadcrumb-item
a(href='/#/backups') a(href='./#/backups')
| PostgreSQL cluster backups ({ stored_clusters.length }) | PostgreSQL cluster backups ({ stored_clusters.length })
p p
@ -63,7 +63,7 @@ restore
p(if='{ versions === null }') p(if='{ versions === null }')
| Error loading backups. Please try again or | Error loading backups. Please try again or
| |
a(href="/") start over a(href="./") start over
| . | .
p(if='{ versions && versions.length === 0 }') p(if='{ versions && versions.length === 0 }')
@ -96,7 +96,7 @@ restore
p(if='{ basebackups === null }') p(if='{ basebackups === null }')
| Error loading snapshots. Please try again or | Error loading snapshots. Please try again or
| |
a(href="/") start over a(href="./") start over
| . | .
p(if='{ basebackups && basebackups.length === 0 }') p(if='{ basebackups && basebackups.length === 0 }')
@ -312,7 +312,7 @@ restore
get_subresources_once({ get_subresources_once({
parent_resource: this, parent_resource: this,
key: 'stored_clusters', key: 'stored_clusters',
url: '/stored_clusters', url: './stored_clusters',
build_subresource: stored_cluster_name => ({ build_subresource: stored_cluster_name => ({
id: 'stored-cluster-' + stored_cluster_name, id: 'stored-cluster-' + stored_cluster_name,
name: stored_cluster_name, name: stored_cluster_name,
@ -324,7 +324,7 @@ restore
body: stored_cluster => get_subresources_once({ body: stored_cluster => get_subresources_once({
parent_resource: stored_cluster, parent_resource: stored_cluster,
key: 'versions', key: 'versions',
url: '/stored_clusters/' + stored_cluster.name, url: './stored_clusters/' + stored_cluster.name,
build_subresource: version_name => ({ build_subresource: version_name => ({
id: stored_cluster.id + '-version-' + version_name, id: stored_cluster.id + '-version-' + version_name,
name: version_name, name: version_name,
@ -340,7 +340,7 @@ restore
parent_resource: version, parent_resource: version,
key: 'basebackups', key: 'basebackups',
url: ( url: (
'/stored_clusters/' + stored_cluster.name './stored_clusters/' + stored_cluster.name
+ '/' + version.name + '/' + version.name
), ),
build_subresource: basebackup => Object.assign(basebackup, { build_subresource: basebackup => Object.assign(basebackup, {

View File

@ -6,19 +6,19 @@ status
ol.breadcrumb ol.breadcrumb
li.breadcrumb-item li.breadcrumb-item
a(href='/#/operator') a(href='./#/operator')
| Workers | Workers
virtual(if='{ operatorShowLogs && logs }') virtual(if='{ operatorShowLogs && logs }')
li.breadcrumb-item { worker_id } li.breadcrumb-item { worker_id }
li.breadcrumb-item li.breadcrumb-item
a(href='/#/operator/worker/{ worker_id }/logs') a(href='./#/operator/worker/{ worker_id }/logs')
| Logs | Logs
virtual(if='{ operatorShowQueue && queue }') virtual(if='{ operatorShowQueue && queue }')
li.breadcrumb-item { worker_id } li.breadcrumb-item { worker_id }
li.breadcrumb-item li.breadcrumb-item
a(href='/#/operator/worker/{ worker_id }/queue') a(href='./#/operator/worker/{ worker_id }/queue')
| Queue | Queue
div(if='{ status }') div(if='{ status }')
@ -44,12 +44,12 @@ status
) )
a.btn.btn-info( a.btn.btn-info(
href='/#/operator/worker/{ worker_id }/logs' href='./#/operator/worker/{ worker_id }/logs'
) )
| Logs | Logs
a.btn.btn-info( a.btn.btn-info(
href='/#/operator/worker/{ worker_id }/queue' href='./#/operator/worker/{ worker_id }/queue'
) )
| Queue | Queue
@ -96,7 +96,7 @@ status
this.pollStatus = () => { this.pollStatus = () => {
jQuery.get( jQuery.get(
'/operator/status', './operator/status',
).done(data => { ).done(data => {
this.update({status: data}) this.update({status: data})
}) })
@ -111,7 +111,7 @@ status
this.pollLogs = id => { this.pollLogs = id => {
jQuery.get( jQuery.get(
'/operator/workers/' + id + '/logs', './operator/workers/' + id + '/logs',
).done(data => { ).done(data => {
data.reverse() data.reverse()
this.update({logs: data}) this.update({logs: data})
@ -120,7 +120,7 @@ status
this.pollQueue = id => { this.pollQueue = id => {
jQuery.get( jQuery.get(
'/operator/workers/' + id + '/queue', './operator/workers/' + id + '/queue',
).done(data => ).done(data =>
this.update({queue: data.List}) this.update({queue: data.List})
) )

View File

@ -62,9 +62,9 @@
<!-- self-hosted --> <!-- self-hosted -->
<link href="/css/styles.css" rel="stylesheet"> <link href="./css/styles.css" rel="stylesheet">
<link href="/css/prism.css" rel="stylesheet"> <link href="./css/prism.css" rel="stylesheet">
<link href="/favicon.png" rel="icon" type="image/png"> <link href="./favicon.png" rel="icon" type="image/png">
</head> </head>
@ -168,8 +168,8 @@
<!-- self-hosted --> <!-- self-hosted -->
<script src="/js/prism.js"></script> <script src="./js/prism.js"></script>
<script src="/js/build/app.js"></script> <script src="./js/build/app.js"></script>
{% if google_analytics %} {% if google_analytics %}
<!-- Global site tag (gtag.js) - Google Analytics --> <!-- Global site tag (gtag.js) - Google Analytics -->