add tab for monthly costs per cluster

This commit is contained in:
Felix Kunde 2020-01-15 13:40:22 +01:00
parent 077f9af4e3
commit 5ba81d60b5
5 changed files with 86 additions and 23 deletions

View File

@ -76,6 +76,9 @@ postgresql
.alert.alert-danger(if='{ progress.requestStatus !== "OK" }') Create request failed .alert.alert-danger(if='{ progress.requestStatus !== "OK" }') Create request failed
.alert.alert-success(if='{ progress.requestStatus === "OK" }') Create request successful ({ new Date(progress.createdTimestamp).toLocaleString() }) .alert.alert-success(if='{ progress.requestStatus === "OK" }') Create request successful ({ new Date(progress.createdTimestamp).toLocaleString() })
.alert.alert-info(if='{ !progress.postgresql }') PostgreSQL cluster manifest pending
.alert.alert-success(if='{ progress.postgresql }') PostgreSQL cluster manifest created
.alert.alert-info(if='{ !progress.statefulSet }') StatefulSet pending .alert.alert-info(if='{ !progress.statefulSet }') StatefulSet pending
.alert.alert-success(if='{ progress.statefulSet }') StatefulSet created .alert.alert-success(if='{ progress.statefulSet }') StatefulSet created

View File

@ -45,12 +45,14 @@ postgresqls
thead thead
tr tr
th(style='width: 120px') Team th(style='width: 120px') Team
th(style='width: 130px') Namespace
th Name
th(style='width: 50px') Pods th(style='width: 50px') Pods
th(style='width: 140px') CPU th(style='width: 140px') CPU
th(style='width: 130px') Memory th(style='width: 130px') Memory
th(style='width: 100px') Size th(style='width: 100px') Size
th(style='width: 130px') Namespace th(style='width: 120px') Cost/Month
th Name th(stlye='width: 120px')
tbody tbody
tr( tr(
@ -58,19 +60,22 @@ postgresqls
hidden='{ !namespaced_name.toLowerCase().includes(filter.state.toLowerCase()) }' hidden='{ !namespaced_name.toLowerCase().includes(filter.state.toLowerCase()) }'
) )
td { team } td { team }
td { nodes }
td { cpu } / { cpu_limit }
td { memory } / { memory_limit }
td { volume_size }
td(style='white-space: pre') td(style='white-space: pre')
| { namespace } | { namespace }
td td
a( a(
href='/#/status/{ cluster_path(this) }' href='/#/status/{ cluster_path(this) }'
) )
| { name } | { name }
td { nodes }
td { cpu } / { cpu_limit }
td { memory } / { memory_limit }
td { volume_size }
td { calcCosts(nodes, cpu, memory, volume_size) }$
td(style='white-space: pre')
| { namespace }
.btn-group.pull-right( .btn-group.pull-right(
aria-label='Cluster { qname } actions' aria-label='Cluster { qname } actions'
@ -124,12 +129,14 @@ postgresqls
thead thead
tr tr
th(style='width: 120px') Team th(style='width: 120px') Team
th(style='width: 130px') Namespace
th Name
th(style='width: 50px') Pods th(style='width: 50px') Pods
th(style='width: 140px') CPU th(style='width: 140px') CPU
th(style='width: 130px') Memory th(style='width: 130px') Memory
th(style='width: 100px') Size th(style='width: 100px') Size
th(style='width: 130px') Namespace th(style='width: 120px') Cost/Month
th Name th(stlye='width: 120px')
tbody tbody
tr( tr(
@ -137,11 +144,6 @@ postgresqls
hidden='{ !namespaced_name.toLowerCase().includes(filter.state.toLowerCase()) }' hidden='{ !namespaced_name.toLowerCase().includes(filter.state.toLowerCase()) }'
) )
td { team } td { team }
td { nodes }
td { cpu } / { cpu_limit }
td { memory } / { memory_limit }
td { volume_size }
td(style='white-space: pre') td(style='white-space: pre')
| { namespace } | { namespace }
@ -151,6 +153,13 @@ postgresqls
href='/#/status/{ cluster_path(this) }' href='/#/status/{ cluster_path(this) }'
) )
| { name } | { name }
td { nodes }
td { cpu } / { cpu_limit }
td { memory } / { memory_limit }
td { volume_size }
td { calcCosts(nodes, cpu, memory, volume_size) }$
td
.btn-group.pull-right( .btn-group.pull-right(
aria-label='Cluster { qname } actions' aria-label='Cluster { qname } actions'
@ -223,6 +232,45 @@ postgresqls
+ '/' + encodeURI(cluster.name) + '/' + encodeURI(cluster.name)
) )
const calcCosts = this.calcCosts = (nodes, cpu, memory, disk) => {
costs = nodes * (toCores(cpu) * opts.config.cost_core + toMemory(memory) * opts.config.cost_memory + toDisk(disk) * opts.config.cost_ebs)
return costs.toFixed(2)
}
const toDisk = this.toDisk = value => {
if(value.endsWith("Gi")) {
value = value.substring(0, value.length-2)
value = Number(value)
return value
}
return value
}
const toMemory = this.toMemory = value => {
if (value.endsWith("Mi")) {
value = value.substring(0, value.length-2)
value = Number(value) / 1000.
return value
}
else if(value.endsWith("Gi")) {
value = value.substring(0, value.length-2)
value = Number(value)
return value
}
return value
}
const toCores = this.toCores = value => {
if (value.endsWith("m")) {
value = value.substring(0, value.length-1)
value = Number(value) / 1000.
return value
}
return value
}
this.on('mount', () => this.on('mount', () =>
jQuery jQuery
.get('/postgresqls') .get('/postgresqls')

View File

@ -61,8 +61,10 @@ spec:
"resources_visible": true, "resources_visible": true,
"users_visible": true, "users_visible": true,
"postgresql_versions": [ "postgresql_versions": [
"12",
"11", "11",
"10", "10",
"9.6" "9.6",
"9.5"
] ]
} }

View File

@ -84,6 +84,13 @@ SUPERUSER_TEAM = getenv('SUPERUSER_TEAM', 'acid')
TARGET_NAMESPACE = getenv('TARGET_NAMESPACE') TARGET_NAMESPACE = getenv('TARGET_NAMESPACE')
GOOGLE_ANALYTICS = getenv('GOOGLE_ANALYTICS', False) GOOGLE_ANALYTICS = getenv('GOOGLE_ANALYTICS', False)
# storage pricing, i.e. https://aws.amazon.com/ebs/pricing/
COST_EBS = float(getenv('COST_EBS', 0.119)) # GB per month
# compute costs, i.e. https://www.ec2instances.info/?region=eu-central-1&selected=m5.2xlarge
COST_CORE = 30.5 * 24 * float(getenv('COST_CORE', 0.0575)) # Core per hour m5.2xlarge / 8.
COST_MEMORY = 30.5 * 24 * float(getenv('COST_MEMORY', 0.014375)) # Memory GB m5.2xlarge / 32.
WALE_S3_ENDPOINT = getenv( WALE_S3_ENDPOINT = getenv(
'WALE_S3_ENDPOINT', 'WALE_S3_ENDPOINT',
'https+path://s3-eu-central-1.amazonaws.com:443', 'https+path://s3-eu-central-1.amazonaws.com:443',
@ -293,6 +300,9 @@ DEFAULT_UI_CONFIG = {
'dns_format_string': '{0}.{1}.{2}', 'dns_format_string': '{0}.{1}.{2}',
'pgui_link': '', 'pgui_link': '',
'static_network_whitelist': {}, 'static_network_whitelist': {},
'cost_ebs': COST_EBS,
'cost_core': COST_CORE,
'cost_memory': COST_MEMORY
} }

View File

@ -1,14 +1,14 @@
Flask-OAuthlib==0.9.5 Flask-OAuthlib==0.9.5
Flask==1.0.2 Flask==1.1.1
backoff==1.5.0 backoff==1.8.1
boto3==1.5.14 boto3==1.10.4
boto==2.48.0 boto==2.49.0
click==6.7 click==6.7
furl==1.0.1 furl==1.0.2
gevent==1.2.2 gevent==1.2.2
jq==0.1.6 jq==0.1.6
json_delta>=2.0 json_delta>=2.0
kubernetes==3.0.0 kubernetes==3.0.0
requests==2.20.1 requests==2.22.0
stups-tokens>=1.1.19 stups-tokens>=1.1.19
wal_e==1.1.0 wal_e==1.1.0